装饰者不改变dir()

时间:2016-11-08 14:54:29

标签: python python-2.7 decorator python-decorators

在没有

的情况下使用Python装饰器
@functools.wraps(function)

更改原始功能的__doc____name__help,这可以理解为装饰器只是

fun=decorate(fun)

但为什么它不改变dir(有趣)的功能?不应该改变吗?

例如:

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)在那里呢?不应该$scope.combineParts = function(part1, part2) { var merged = angular.copy( part1 ); for ( key in part1 ) { if ( part2.hasOwnProperty(key) ) merged[key].push.apply(merged[key], part2[key]) } return merged; } 有趣。名称给出了装饰者

2 个答案:

答案 0 :(得分:2)

你似乎错过了装饰者的关键一步。你确实在函数@decorate上使用装饰器fun来做到这一点:

fun = decorate(fun)

然后不要跟进。 fun现在绑定到装饰器的返回值。

你说:

  

Python装饰器[...]更改原始函数的__doc____name__help

事实并非如此。原始的,未修饰的功能没有变化。它仍然具有相同的__doc__,相同的__name__等。来自装饰器的返回的对象,现在绑定到原始名称,但是,可能有不同的名称或docstring。毕竟,它可能完全是不同的对象

在您的示例中,您从装饰器返回__wow,因此Python将该对象分配给funfun 这里只是一个名称,一个引用装饰器的结果。 原始 fun功能不再通过该名称提供;在没有点你在这里检查原始的,未修饰的功能。

因此,在名称 dir()上使用fun表示它适用于现在绑定的任何fun,即__wow由装饰者产生的功能。在fun上设置属性,在同一个函数对象上设置属性。所有属性都反映了这一点。

您可能会发现逐步完成Python的工作并将这些步骤可视化很有帮助。见Python Tutor visualisation;它向您显示最终的fun引用(以及原始函数对象最终的位置):

references in the Python Tutor visualisation

答案 1 :(得分:0)

函数的

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']

您如何判断这些是原始函数的属性名称还是包装函数的属性名称?在任何一种情况下,它都是完全相同的列表。