从2.4版本开始(对于类是2.6),Python允许您使用另一个函数来修饰函数:
def d(func): return func
@d
def test(first): pass
这是一种方便的语法糖。你可以使用装饰器完成各种有趣的事情,而不会弄乱代码。然而,如果你想找到被装饰的原始函数,你必须通过一些麻烦的方式(比如Cls.method.__func__.__closure__[0].cell_contents或者更糟)。
我发现自己希望有一个更好的方法,并发现python-dev上有一些讨论,关于在由装饰器返回的[新]函数中添加一个名为__decorated__的变量。然而,似乎没有任何进展。
作为一个爱冒险的人,我已经有了大约4年的Python编程经验,我想看看在Python编译器源码中实现__decorated__会怎样。老实说,我从未深入了解过C语言,所以我的前几个小时都是在试图理解底层C代码的工作原理。那么,首先,了解我需要改变/添加哪些内容以实现__decorator__的最佳资源是什么? 其次,如果装饰器返回一个新函数,那么
__decorated__
将只返回原始的已装饰函数。然而,如果装饰器返回原始函数,那么应该发生什么呢?我想到了三个选项(第三个是我最喜欢的):
- 不添加
__decorator__
。 - 添加
__decorator__
但将其设置为None。 - 添加
__decorator__
并将其设置为原始函数。
更新:
有人提醒我了我忽略的一种情况。当装饰器既不返回原始函数也不返回包裹原始函数的函数时会发生什么?此时没有任何东西保留对原始函数的引用,它将被垃圾回收。(感谢Oddthinking!)
在这种情况下,我认为我仍然会选择第三个选项。装饰器返回的对象将获得一个名为
__decorated__
的名称,该名称引用原始函数。这意味着它不会被垃圾回收。对我来说,从类定义中返回的函数因为你装饰它而完全消失似乎很奇怪。在我看来,这更加需要为每个装饰器应用一个
__decorated__
属性。然而,更可能的是我的直觉有误,当前的行为是大多数人所期望的。有任何想法吗?附言:这是我先前更一般的问题的延伸。我还通过单独发布了第一部分的更多信息。
@property
中怎么用?也就是说,装饰器根本不需要返回函数。 - habnabit__decorated__
添加到返回的任何内容中,无论是函数还是其他。 - Eric Snow