本文介绍了python中的装饰器类的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读一些Python模块时,我遇到了这个装饰器类:

While reading up about some python module I encountered this decorator class:

# 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)

我所知道的装饰器,是可以扩展功能(例如,针对某个功能)。有人会这么友善并向我解释为什么上面的类很有用,并且它是如何工作的

What I know about decorators, is that the can extend functionality (e.g. for a function). Could someone be so kind and explain to me why the class above is useful and how it exactly works?

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

It is used in the code this way:

@omnimethod:
def some_function(...):
    pass

另一个问题:

I encountered this piece of code in the same file:

@property
def some_other_function(...):
    pass

@property 不在文件中的任何位置定义。这是一些标准的装饰器吗?如果是,它有什么作用? Google无法在这种情况下为我提供帮助。

@property is not defined anywhere in the file. Is this some standard decorator? If yes, what does it do? Google couldn't help me on this case.

顺便说一句,这是我找到代码的来源:

By the way, here is the source where I found the code: http://code.xster.net/pygeocoder/src/c9460febdbd1/pygeocoder.py

推荐答案

全能方法非常聪明。它使用一些非常巧妙的技巧来完成任务。让我们从头开始。

that omnimethod is very clever. It uses some very subtle tricks to do it's job. Let's start at the beginning.

您可能已经知道只是函数应用的糖,即:

You probably already know that decorator syntax is just sugar for function application, ie:

@somedecorator
def somefunc(...):
    pass

# is the same thing as    

def somefunc(...):
    pass
somefunc = somedecorator(somefunc)

所以 somefunc 是实际上是 omnimethod 实例,而不是已定义的函数。有趣的是 omnimethod 还实现了如果类属性定义了 __ get __ 方法,则每当提及该属性时,解释器而是在该对象上调用 __ get __ 并返回该值,而不是返回属性本身。

so somefunc is actually an omnimethod instance, not the function that had been defined. what's interesting about this is that omnimethod also implements the descriptor interface. If a class attribute defines a __get__ method, then whenever that attribute is mentioned, the interpreter instead calls __get__ on that object, and returns that instead of returning the attribute itself.

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

the __get__ method is always called with instance as first argument, and the class of that instance as second argument. If the attribute was actually looked up from the class itself, then instance will be None.

最后一个骗术是,是的python方法。当您使用 partial 时,您将一个函数和一些参数传递给它,并且它返回一个新函数,该函数在被调用时还将使用原始参数调用原始函数。您以后传入的任何参数。 全方位方法使用此技术将 self 参数填充到其包装的函数中。

The last bit of trickery is functools.partial, which is the python way of function currying. when you use partial, you pass it a function and some arguments, and it returns a new function, that when called, will call the original function with the original arguments in addition to whichever arguments you passed in later. omnimethod uses this technique to populate the self parameter to the function it wraps.

这里是这样。从实例读取但无法使用从班级本身。您会收到未绑定的TypeError

Here's what that looks like. a regular method can be called when you read it from an instance but you can't use it from the class itself. you get an unbound 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装饰器(还有 staticmethod ,但不要紧),将允许您在类级别使用它,但是永远看不到实例。

Python provides a bultin decorator classmethod (and also staticmethod, but nevermind that), that will allow you to use it at the class level, but it never gets to see the instance. it always recieves the class as it's first 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
>>> 

由于有点聪明,全能方法给出了

>>> 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中的装饰器类的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-10 22:24