【问题标题】:Decorators and in class装饰师和课堂
【发布时间】:2010-10-16 23:09:27
【问题描述】:

有没有办法在嵌套良好的类结构中编写装饰器?例如,没有类也可以正常工作:

def wrap1(func):
    def loc(*args,**kwargs):
        print 1
        return func(*args,**kwargs)
    return loc

def wrap2(func):
    def loc(*args,**kwargs):
        print 2
        return func(*args,**kwargs)
    return loc


def wrap3(func):
    def loc(*args,**kwargs):
        print 3
        return func(*args,**kwargs)
    return loc

def merger(func):
    return wrap1(wrap2(wrap3(func)))


@merger
def merged():
    print "merged"


@wrap1
@wrap2
@wrap3
def individually_wrapped():
    print "individually wrapped"

merged()
individually_wrapped()

输出是:

1
2
3
merged
1
2
3
individually wrapped

这就是我想要的。但现在假设我想将mergedindividually_wrapped 设为静态或类方法。只要将装饰器保持在类命名空间之外,这也将起作用。有没有什么好方法可以将装饰器放在命名空间中?我宁愿不列举所有不起作用的方法,但主要问题是如果merger 是一个方法,它就无法访问wrapX 方法。也许这是一件愚蠢的事情,但是有没有人让这样的东西工作,所有装饰器和装饰方法都在同一个类中?

【问题讨论】:

    标签: python decorator


    【解决方案1】:

    “有没有什么好的方法可以将装饰器放在命名空间中?”

    没有令人信服的理由。你有模块文件。这些是一个类和一些装饰器的整洁容器。

    你永远不需要装饰器作为类的方法——你可以从另一个方法调用一个方法。

    【讨论】:

    • 我认为这是要走的路。没有很好的理由让他们留在课堂上。
    【解决方案2】:

    实际上,将它们全部放在一个类中应该没有问题。在类体内时,您可以简单地通过命名来命名迄今为止定义的任何变量:

    A类(对象): a = 1 b = 2 c = a + b 打印交流电

    这会产生结果 3,因为当 Python 执行类主体时,函数可以“看到”已声明的变量 a 和 b。所以以下也有效:

    B类(对象): @静态方法 def 包装器(*args,**kw): ... @包装器 定义一个(...): ...

    现在,您的合并功能怎么样?问题是包装函数在类主体完成执行之后运行很长时间,并且它定义的变量不再在封闭范围内。那你怎么能引用他们呢?通过使用类的名称作为前缀!像这样:

    C类(对象): @静态方法 def wrap1(*args, **kw): ... @静态方法 def wrap2(*args, **kw): ... @静态方法 def wrap3(*args, **kw): ... @静态方法 def 合并(*args, **kw): C.wrap1(C.wrap2(C.wrap3(...))) @合并 def 普通(...): ...

    因此,Python 的一般规则是:在类主体级别运行的代码可以讨论迄今为止在其中定义的所有变量和方法,这意味着您可以将这些类变量用作包装纸。但是一旦你在类中的一个函数的“内部”,无论它是一个类函数、一个静态函数还是一个方法(这个包装器是一个类方法,因为它需要 args 但没有“self”),那么你必须使用要“获取”其内容的类的名称。

    【讨论】:

    • 好点。如果我必须按名称引用类来执行此操作,那么可能没有充分的理由将它们放在类中。
    • 是的,如果您只是想让引用它们变得更容易,可能没有理由这样做。您可以将包装器留在类之外,然后可以从类定义内部及其任何函数内部“看到”它们。可能会让事情变得更简单!
    猜你喜欢
    • 2015-06-29
    • 2020-07-24
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    相关资源
    最近更新 更多