关于python:如何在一个类中修饰所有方法?我可以装饰一下class吗?

How to decorate all methods in a class? Can I just decorate the class?

本问题已经有最佳答案,请猛点这里访问。

我有几个类,它们有相同的实现名,但实现不同。我想在一些类中装饰所有方法,但其他类不想。我考虑过继承,但是有些类有一些方法不需要修饰。问题是,我不想一个接一个地装饰方法,有些类需要由同一个装饰器来装饰,有没有解决办法?


您可以启动所有需要用一些前缀修饰的方法,然后使用类似这样的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Xobject(object):

    def __init__(self, decorator):
        for method_name in dir(self):
            if method_name.startswith("dec_"):
                attr = getattr(self, method_name)
                wrapped = decorator(attr)
                setattr(self, method_name, wrapped)

    def dec_me_1(self):
        print("In dec_me1")
        return 0

    def dec_me_2(self):
        print("In dec_me2")
        return 1


def decorator(func):

    def wrapped(*args):
        print("TEST")
        return func(*args)

    return wrapped


x = Xobject(decorator)

x.dec_me_1()
x.dec_me_2()

更新:

您可以通过下面的函数来装饰类。使用python时,您应该知道python中的class也是对象,因此您可以更改它并将其传递给另一个函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def decorator(func):

    def wrapped(*args):
        print("TEST")
        return func(*args)

    return wrapped


def decorate_object(p_object, decorator):
    for method_name in dir(p_object):
        if method_name.startswith("dec_"):
            attr = getattr(p_object, method_name)
            wrapped = decorator(attr)
            setattr(p_object, method_name, wrapped)

decorate_object(Xobject, decorator)

x = Xobject()

x.dec_me_1()
x.dec_me_2()

您也可以用同样的方式装饰已经实例化的对象:

1
2
3
4
5
6
7
8
9
x = Xobject()

x.dec_me_1()
x.dec_me_2()

decorate_object(x, decorator)

x.dec_me_1()
x.dec_me_2()


在某种程度上,你必须明确什么会被包装,什么不会。

如果我理解正确,我想你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def wrapper(func):
    def inner(*args, **kwargs):
        print"%s was called" func.__name__
        return func(*args, **kwargs)
    return inner

class A(object):
    def foo(self):
        print"foo called"
    def bar(self):
        print"BAR CALLED"

class B(A):
    @wrapper
    def foo(self):
        super(B, self).foo()

class C(A):
    @wrapper
    def bar(self):
        super(C, self).bar()

Stick = A()
Dave = B()
Jupiter = C()

Jupiter.foo() #prints"foo called"
Jupiter.bar() #prints"bar wrapped" and"BAR CALLED"


我相信有几种方法可以解决这个问题,但主要的选择是:

  • 创建一个自定义元类,其中__new__方法遍历属性字典,标识方法并对它们进行修饰。参见http://eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example/了解python元类编程的示例。缺点:这可能比我们想进入这里要复杂得多。
  • 在常规类的__init__方法中也要这样做。缺点:它只修饰实例方法,而不是类或静态方法,而且速度较慢,因为它在每次创建新实例时都会运行。
  • 课外活动:

    1
    2
    3
    4
    5
    6
    class Foo(object):
      def bar(self):
        print 'bar'

    for name, ref in vars(Foo):
      if callable(ref): ...

    缺点:你只有一次机会做得对:在进口的时候。子类不会被修改。

  • 在类级修饰器中进行。和在课堂外做同样的缺点(我想)。