Python: decorator, jak předat instance-member proměnnou at runtime?

honza

Dobry den,

mam dekorator @cache(size=xxx), chtel bych jeho hodnotu nastavovat az podle parametru tridy ve ktere je pouzit, ale nedari se mi pristoupt k ani jednomu z instance, class, static, global promennych. Asi lepsi ukazka kyzeneho stavu v (pseudo) pythonu:

Kód: [Vybrat]
# dekorator
def cache(f):
  ...

class A():
  def __init__(self, cacheSize=0):
    self.cacheSize = cacheSize

  @cache(maxsize=self.cacheSize) # tohle nejde..hledal jsem vsemozne pristupy
  def long_method(self,x):
    ...

# pouziti
a=A(5)
a.long_method(3)


dekuji moc za vysvetleni!


somemonster

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #1 kdy: 28. 08. 2015, 11:50:22 »
Ten dekorator je executovany pri vytvoreni classy a vtedy self neexistuje, self vznika pri vytvoreni instancie. Co mozes urobit je v inner funkcii  ten parameter vytiahnut z funkcie long_method kedze ta pasne dekoratoru aj svoj self.

Ondrej

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #2 kdy: 28. 08. 2015, 12:40:02 »
Zdravím,

Toto jde udělat vcelku jednoduše:

from functools import wraps

def cache(f):
    print "Dekoruji."
    @wraps(f)
    def decorated_func(self, *args, **kwargs):
        print self # tady je možné dělat se self cokoliv
        return f(self, *args, **kwargs)
    return decorated_func

honza

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #3 kdy: 28. 08. 2015, 13:22:23 »
Dekuji za odpovedi,
muj problem je, ze to co chci wrappnout, abych mohl predat self.xxx parametr neni moje funkce, ale uz dekorator, ktery vyzaduje jeden argument.
tedy:

Kód: [Vybrat]
# orig wrapper, ktery nemuzu menit (c++ binding), pouziva se takto:
@origcache(maxsize=3)
def long_foo(n):
  pass

# muj cil: vytvorit @mycache ktery precte self.cacheSize z contextu sve instance?
# a bude pritom volat @origcache
class A():
  def __init__(cacheSize):
    self.cacheSize = cacheSize

  @mycache
  def long_foo(n):
    pass

Z Vasich odpovedi chapu proc to nefunguje, ale neumim si priohnout @wraps tak, aby mi opravovalo dekorator. Nasel jsem neco o dekoratorech/descriptorech ...ale v tom se uprimne moc nevyznam.

Diky

matous

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #4 kdy: 28. 08. 2015, 16:09:53 »
Koukni se na https://wiki.python.org/moin/PythonDecoratorLibrary
Je tam Memoize. To je velice podobné tomu co chceš.


honza

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #5 kdy: 28. 08. 2015, 17:40:51 »
Memoize znam, to je pouze implementace cache, tu uz mam. Me jde o to, jak dekoratoru predat argument ze self.neco

pokus

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #6 kdy: 28. 08. 2015, 20:47:09 »
?

Kód: [Vybrat]
def origcache(f,size=3):
    def g(*args,**kwds):
        #print(*args, **kwds)
        print('Calling decorated function',size)
        return f(*args, **kwds)
    return g


metaCache={}
def cache(f):
    def g(*args,**kwds):
        try:
            return metaCache[(f,args[0])](*args[1:],**kwds)
        except KeyError:
            print("defining")
            newf=origcache(f,size=args[0].s)
            metaCache[(f,args[0])]=newf
            return newf(*args[1:],**kwds)
        else:
            return
    return g


class A():
    def __init__(self):
        self.s=5

    @cache
    def f(x):
        return str(x)+"aa"


a=A()
print(a.f(2))
print(a.f(2))

Kit

Re:Python: decorator, jak předat instance-member proměnnou at runtime?
« Odpověď #7 kdy: 28. 08. 2015, 22:05:40 »
Zkus to bez cache!