[python] Dekorátor

Radek radek.hnilica na gmail.com
Středa Únor 16 15:23:07 CET 2011


Dobrý den,

nejdřív bych se uvedl, jsem takový opakovaný začátečník,  k Pythonu
jsem naposled přičichl možná před osmi lety a nic moc.  Teď, asi tři
měsíce zpátky jsem se k němu vrátil, protože si hraju s GAE/P.  Přes
všechny problémy se zkouším prokousávat, ikdyž python bolí, ale teď
jsem se tak nějak úplně ztratil.  Pokouším se udělat Basic HTTP
auhorizaci, respektive se ji pokouším zabalit do inteligentního
dekorátoru.

Byl by tady někdo, kdo by mě mohl odkázat na rozumný studijní
materiál, podtrhuji rozumný, ze kterého bych byl schopen pochopit, jak
funguje dekorátor který definuju jako třídu.  S dekorátory jako
funkcemi jsem se nějak popasoval, tedy aspoň si to myslim, ale u té
třídy je to pro mě černá magie.

Pokud nemá dekorátor parametry, tak se zdá že to nějak chápu.  Do
__init__ je předána dekorovaná fuknce a do __call__ jsou pak předávány
argumenty té funkce viz:

class mydec:
    def __init__(self, fce):
        self.fce = fce   # Store, we will use it in __call__

    def __call__(self, *args, **kwds):
        ....pre
        result = self.fce(*args, **kwds)
        .....post
        return result

@mydec
def myfunc(*args, **kwds):
    pass

Ale pokud má mít dekorátor parametry, tak jsem sice našel/zkonstruoval
kód který se zdá fungovat, ale plně mu nerozumím.  Následující je
vystřiženo z testovacího skriptu.

class Authorize:
    def __init__(self, allow = None, deny = None):
        self.allow = allow; self.deny  = deny
        print 'Authorize.__init__(allow=%s, deny=%s)' % (allow,deny)

    def __call__(self, function):
        def decoratedFunction(?context, *args, **kwds):  # context
must be if we decorated class method, its a self.
            print 'Authorize.__call__ in decorator, before function
with: %s, %s' % (str(args), str(kwds))
            self.helper() # Just to test if I can call
            result = function(*args, **kwds)
            print 'in decorator, after function, result: %s' %
str(result)
            return result

        return decoratedFunction

    def helper(self):
        print 'Authorize.helper()'

@Authorize()
def get(key, action):
    print 'get(%s, %s)' % (key, action)
    return 'ola'

Jen tím že chci aby měl dekorátor parametry, se tak radikálně změní
kód dekorátoru.
Potřeboval bych nějak po lopatě vědět, co se uvnitř děje, protože
cítím že ty dekorátory budu určitě používat ještě mnohem divočeji.

Jen tak mimochodem, v tuto chíli se snažím mít něco co v aplikaci
použiju asi takto:

class UserHandler(ApplicationHandler):   # ApplicationHandler is
subclass of webapp.RequestHandler

    @Authorize(model=User, allow=['karel', 'admin'], deny=['pavel'])
    def get(self, key=None, action=None):
        ..... process GET request knowing that
        ..... self.loged_user is the current authorized user


Další informace o konferenci Python