python - Python 中修饰函数和方法之间的行为差​​异

标签 python python-2.7 python-decorators

我对“Pythonic 静态变量”使用以下解决方法:

def static_vars(**kwargs):
    """decorator for funciotns that sets static variables"""
    def decorate(func):
        for k, v in kwargs.items():
            setattr(func, k, v)
        return func
    return decorate

@static_vars(var=1)
def global_foo():
    _ = global_foo
    print _.var
    _.var += 1

global_foo()  # >>> 1
global_foo()  # >>> 2

它按预期工作。但是当我在类中移动这样一个修饰函数时,我得到了一个奇怪的变化:

class A(object):
    @static_vars(var=1)
    def foo(self):
        bound = self.foo
        unbound = A.foo
        print bound.var  # OK, print 1 at first call
        bound.var += 1   # AttributeError: 'instancemethod' object has no attribute 'var'

    def check(self):
        bound = self.foo
        unbound = A.foo
        print 'var' in dir(bound)
        print 'var' in dir(unbound)
        print bound.var is unbound.var  # it doesn't make much sense but anyway

a = A()
a.check()  # >>> True
           # >>> True
           # >>> True

a.foo()    # ERROR

我看不出是什么原因导致了这种行为。在我看来,它与 python 描述符协议(protocol)、所有绑定(bind)与非绑定(bind)方法的内容有关。不知何故,foo.var 属性可以访问但不可写。

感谢任何帮助。

附注我知道静态函数变量本质上是类变量,在第二种情况下这个装饰器是不必要的,但问题更多的是理解 Python 的底层,而不是获得任何可行的解决方案。

最佳答案

a.foo 不会返回您定义的实际函数;它返回它的一个绑定(bind)方法,该方法包装该函数并将 self 分配给 a

https://docs.python.org/3/howto/descriptor.html#functions-and-methods

不过,该指南有点过时了,因为未绑定(bind)的方法仅返回 Python 3 中的函数。

因此,要访问函数的属性,您需要通过 A.foo (或 a.foo.__func__)而不是 a。 foo.这仅适用于 Python 3。在 Python 2 中,我认为 A.foo.__func__ 会起作用。

关于python - Python 中修饰函数和方法之间的行为差​​异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34286451/

相关文章:

Python非线性切片

python - Twitter 搜索 API 参数

python - 作为装饰器的类方法

python - 有@staticmethod 和没有它的区别

python - 如何在python中识别不同颜色/肤色的相同表情符号?

python - 如何删除使用 distutils 安装的程序?

python-2.7 - 有没有办法使用 ssh 和 Python 将二进制流传输到远程服务器?

google-app-engine - ndb.BlobProperty 与 BlobStore : which is more private and more secure

python-2.7 - 如何将变量作为列名传递 pandas

python - 为 Python 数据类编写装饰器