python中一个装饰器类的解释

Auf*_*ind 3 python properties decorator

在阅读一些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)
Run Code Online (Sandbox Code Playgroud)

我对装饰器的了解是,可以扩展功能(例如,用于功能).有人可以这么善良并向我解释为什么上面的课程有用以及它是如何工作的

它以这种方式在代码中使用:

@omnimethod:
def some_function(...):
    pass
Run Code Online (Sandbox Code Playgroud)

另一个问题:

I encountered this piece of code in the same file:

@property
def some_other_function(...):
    pass
Run Code Online (Sandbox Code Playgroud)

@property未在文件中的任何位置定义.这是一些标准的装饰者吗?如果是的话,它会做什么?谷歌无法帮助我解决这个问题.

顺便说一句,这里是我找到代码的源代码:http://code.xster.net/pygeocoder/src/c9460febdbd1/pygeocoder.py

Sin*_*ion 5

那个omnimethod非常聪明.它使用一些非常微妙的技巧来完成它的工作.让我们从头开始吧.

您可能已经知道装饰器语法只是函数应用程序的糖,即:

@somedecorator
def somefunc(...):
    pass

# is the same thing as    

def somefunc(...):
    pass
somefunc = somedecorator(somefunc)
Run Code Online (Sandbox Code Playgroud)

所以somefunc实际上是一个omnimethod实例,而不是已经定义的函数.有趣的是,omnimethod它还实现了descriptor界面. 如果class属性定义了一个__get__方法,那么无论何时提到该属性,解释器都会调用__get__该对象,并返回该属性而不是返回该属性本身.

__get__始终使用instance作为第一个参数调用该方法,并将该实例的类作为第二个参数调用.如果该属性实际上是从类本身查找的,则实例将是None.

最后一点技巧是functools.partial,这是函数currying的python方式.当你使用partial它时,你传递一个函数和一些参数,它返回一个新函数,当被调用时,除了你稍后传递的参数之外,还将使用原始参数调用原始函数. omnimethod使用此技术将self参数填充到它包装的函数.

这就是它的样子.一个普通的方法,当你从一个实例看,但你不能从类本身使用它可以被调用.你得到一个未绑定的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)
>>> 
Run Code Online (Sandbox Code Playgroud)

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
>>> 
Run Code Online (Sandbox Code Playgroud)

通过它的聪明,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
>>> 
Run Code Online (Sandbox Code Playgroud)