omniméthode est très intelligent. Il utilise des astuces très subtiles pour faire son travail. Commençons au début.
Vous savez probablement déjà que decorator syntax est juste du sucre pour l'application de la fonction, à savoir:
@somedecorator
def somefunc(...):
pass
# is the same thing as
def somefunc(...):
pass
somefunc = somedecorator(somefunc)
donc somefunc
est en fait une instance omnimethod
, pas la fonction qui avait été défini. ce qui est intéressant à ce sujet est que omnimethod
implémente également le descriptor
interface. Si un attribut de classe définit une méthode __get__
, alors chaque fois que cet attribut est mentionné, l'interpréteur appelle à la place __get__
sur cet objet, et le retourne au lieu de renvoyer l'attribut lui-même.
La méthode __get__
est toujours appelée avec l'instance en tant que premier argument, et la classe de cette instance en second argument. Si l'attribut a été recherché dans la classe elle-même, l'instance sera None
.
Le dernier truc de supercherie est functools.partial
, qui est la manière python de la fonction currying. Lorsque vous utilisez partial
, vous lui passez une fonction et quelques arguments, et il retourne une nouvelle fonction qui, lorsqu'elle sera appelée, appellera la fonction d'origine avec les arguments d'origine en plus des arguments que vous aurez transmis plus tard. omnimethod
utilise cette technique pour remplir le paramètre self
à la fonction qu'il enveloppe.
Voici à quoi cela ressemble. un regular method peut être appelé lorsque vous le lisez depuis une instance mais vous ne pouvez pas l'utiliser depuis la classe elle-même.vous obtenez un TypeError non lié
>>> class Foo(object):
... def bar(self, baz):
... print self, baz
...
>>> f = Foo()
>>> f.bar('apples')
<__main__.Foo object at 0x7fe81ab52f90> apples
>>> Foo.bar('quux')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with
Foo instance as first argument (got str instance instead)
>>> Foo.bar(None, 'quux')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with
Foo instance as first argument (got NoneType instance instead)
>>>
Python fournit un décorateur bultin classmethod
(et aussi staticmethod
, mais tant pis que), qui vous permettra de l'utiliser au niveau de la classe, mais il ne fait jamais de voir l'instance. toujours reçoit la classe comme son premier argument.
>>> class Foo(object):
... @classmethod
... def bar(cls, baz):
... print cls, baz
...
>>> f = Foo()
>>> Foo.bar('abc')
<class '__main__.Foo'> abc
>>> f.bar('def')
<class '__main__.Foo'> def
>>>
Par c'est peu d'astuce, omnimethod
vous donne un peu des deux.
>>> class Foo(object):
... @omnimethod
... def bar(self, baz):
... print self, baz
...
>>> f = Foo()
>>> Foo.bar('bananas')
None bananas
>>> f.bar('apples')
<__main__.Foo object at 0x7fe81ab52f90> apples
>>>
http://wiki.python.org/moin/PythonDecorators#What_is_a_Decorator – krs1
Si vous ne trouvez pas ce que 'property' est, a besoin de votre Google-fu travail: recherche de « propriété python » et vous accéder rapidement à des choses comme http://docs.python.org/library/functions.html#property. Et de là à des choses comme http://docs.python.org/glossary.html#term-decorator –