这个万能方法非常聪明。它使用一些非常微妙的技巧来完成它的工作。让我们从头开始吧。
你可能已经知道了装饰器语法 http://docs.python.org/reference/compound_stmts.html#function-definitions只是函数应用的糖,即:
@somedecorator
def somefunc(...):
pass
# is the same thing as
def somefunc(...):
pass
somefunc = somedecorator(somefunc)
so somefunc
实际上是一个omnimethod
实例,而不是已定义的函数。有趣的是omnimethod
还实施了descriptor界面。 http://docs.python.org/reference/datamodel.html#implementing-descriptors如果一个类属性定义了__get__
方法,那么每当提到该属性时,解释器都会调用__get__
在该对象上,并返回该对象而不是返回属性本身。
the __get__
调用方法时始终将实例作为第一个参数,将该实例的类作为第二个参数。如果属性实际上是从类本身查找的,那么实例将是None
.
最后一点诡计是functools.partial http://docs.python.org/library/functools.html#functools.partial,这是Python的函数方式currying http://en.wikipedia.org/wiki/Currying。当你使用partial
,你向它传递一个函数和一些参数,它返回一个新函数,当调用该函数时,除了你稍后传入的参数之外,还将使用原始参数调用原始函数。omnimethod
使用此技术来填充self
它包装的函数的参数。
看起来是这样的。 A常规方法 http://docs.python.org/tutorial/classes.html#method-objects当您从实例读取它时可以调用它,但不能从类本身使用它。你会得到一个未绑定的 TypeError
>>> 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提供了一个内置的装饰器classmethod http://docs.python.org/library/functions.html#classmethod(并且staticmethod
,但没关系),这将允许您在类级别使用它,但它永远不会看到实例。它always接收类作为其第一个参数。
>>> 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
>>>
凭借着一点小聪明,omnimethod
两者兼而有之。
>>> 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
>>>