- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在阅读一些 python 模块时,我遇到了这个装饰器类:
# this decorator lets me use methods as both static and instance methods
class omnimethod(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return functools.partial(self.func, instance)
我对装饰器的了解是,它可以扩展功能(例如一个函数)。有没有好心人给我解释一下为什么上面的类有用,它到底是怎么工作的?
在代码中是这样使用的:
@omnimethod:
def some_function(...):
pass
另一个问题:
I encountered this piece of code in the same file:
@property
def some_other_function(...):
pass
@property
未在文件中的任何位置定义。这是一些标准的装饰器吗?如果是,它有什么作用?在这种情况下,Google 无法帮助我。
顺便说一句,这是我找到代码的来源:http://code.xster.net/pygeocoder/src/c9460febdbd1/pygeocoder.py
最佳答案
那个万能的方法非常聪明。它使用一些非常微妙的技巧来完成它的工作。让我们从头开始。
您可能已经知道 decorator syntax只是函数应用的糖,即:
@somedecorator
def somefunc(...):
pass
# is the same thing as
def somefunc(...):
pass
somefunc = somedecorator(somefunc)
所以 somefunc
实际上是一个 omnimethod
实例,而不是已经定义的函数。有趣的是 omnimethod
还实现了 descriptor
interface.如果一个类属性定义了一个 __get__
方法,那么每当提到该属性时,解释器都会在该对象上调用 __get__
并返回它而不是返回属性本身。
__get__
方法总是以实例作为第一个参数调用,该实例的类作为第二个参数。如果该属性实际上是从类本身查找的,则实例将为 None
。
最后一点诡计是functools.partial
,这是函数的python方式currying .当您使用 partial
时,您将一个函数和一些参数传递给它,它返回一个新函数,该函数在被调用时将使用原始参数调用原始函数以及您稍后传入的任何参数. omnimethod
使用此技术将 self
参数填充到它包装的函数中。
这是它的样子。一个regular method当您从实例中读取它时可以调用它,但您不能从类本身使用它。你得到一个未绑定(bind)的 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 提供了一个 bultin 装饰器 classmethod
(还有 staticmethod
,但没关系),这将允许您在类级别使用它,但它永远不会看到实例。它总是接收类作为它的第一个参数。
>>> 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
>>>
关于python - python中一个装饰器类的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6598534/
我刚开始使用 Dagger 2,想知道与我目前用来实现依赖注入(inject)的技术相比,它有什么优势。 目前,为了实现 DI,我创建了一个具有两种风格的项目:mock 和 prod。在这些风格中,我
我是一名优秀的程序员,十分优秀!