Python 装饰程序不更改目录()

Python 装饰程序不更改目录(),python,python-2.7,decorator,python-decorators,Python,Python 2.7,Decorator,Python Decorators,使用Python装饰程序时不使用 @functools.wraps(function) 更改原始函数的\uuuu doc\uuuu,\uuuu name\uuuu,帮助,这是可以理解的,因为decorator很简单 fun=decorate(fun) 但是为什么它不改变这个函数的dir(fun)呢?它不也应该改变吗 例如: def wow(func): def __wow(): return func() return __wow @wow def fun(

使用Python装饰程序时不使用

@functools.wraps(function)
更改原始函数的
\uuuu doc\uuuu
\uuuu name\uuuu
帮助
,这是可以理解的,因为decorator很简单

fun=decorate(fun)
但是为什么它不改变这个函数的dir(fun)呢?它不也应该改变吗

例如:

def wow(func):
    def __wow():
        return func()
    return __wow

@wow
def fun():
    print "yes"
fun.b=1
print fun.__name__
print dir(fun)
输出是

__wow   => name of decorator
[...   '__sizeof__', '__str__', '__subclasshook__', 'b', 'func_closure', ...]
                                                    ^^
如果你在这里看到,当我们打印
name
时,它是
decorator
的,但是当我们打印
dir
时,它的
fun
的,因为
b
在那里。那么为什么
b
在那里?它不应该是
dir(decorator)
的乐趣。name给出了decorator的乐趣。
dir()函数的
将返回如下内容:

>>> dir(f)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

您怎么知道这些是原始函数的属性名,还是包装函数的属性名?这两种情况下的列表都完全相同。

您似乎错过了装饰器的一个关键步骤。在函数
fun
上使用decorator
@decoration
可以做到以下几点:

fun = decorate(fun)
但是不要坚持到底
fun
现在绑定到装饰器的返回值

你说:

Python decorators[…]更改原始函数的
\uuuuu doc\uuuuuuuuu
\uuuuu name\uuuuuuuuuu
帮助

事实并非如此。原始的未修饰函数保持不变。它仍然具有相同的
\uuuuu doc\uuuuuu
、相同的
\uuuu名称\uuuuuuuuu
,等等。但是,装饰程序返回的对象现在绑定到原始名称,很可能具有不同的名称或docstring。毕竟,它很可能是一个完全不同的对象

在示例中,您从decorator返回了
\uuuwow
,因此Python将该对象分配给
fun
fun
在这里只是一个名称,它引用了装饰器的结果。原来的
fun
功能不再通过该名称提供;在这里,您决不会检查原始的、未修饰的函数

因此,在名称上使用
dir()
意味着它应用于
fun
现在绑定到的任何东西,这就是装饰程序生成的
\uuwow
函数。在
fun
上设置属性,在同一个函数对象上设置属性。所有属性都反映了这一点

您可能会发现逐步了解Python所做的事情并将这些步骤可视化是很有帮助的。看这个,;它向您展示了
fun
最后引用的内容(以及原始函数对象的结束位置):


您希望有什么不同?@vks:您正在对装饰结果应用属性和
dir()
。您只需在该对象上设置一个新属性,当然
dir()
将包含该属性。我也要求您明确说明:您只在
dir()
中突出显示
'b'
。你没想到它会在那里吗?请解释输出的惊人之处以及为什么。函数是对象。您从decorator返回了
\uuuuwow
,因此Python将该对象分配给
fun
fun
在这里只是一个名称,它引用了装饰器的结果。如果您添加一个类似
fun.c=1
的属性,那么您可以查看yourself@vks:您确实需要在函数中添加一个。用代码向我们展示这些步骤,并解释这些步骤产生的输出如何与您的预期输出不匹配。