如何装饰类中的所有方法?我可以装饰这门课吗?

时间:2014-04-22 15:53:47

标签: python

我有几个类,它们具有相同的实现名称但差异实现。我想装饰一些类中的所有方法,但其他类没有。我已经考虑过继承,但有些类有一些方法不需要进行修饰。问题是我不想逐个装饰方法,有些类需要由同一个装饰器装饰,有没有解决方法可以修复它?

3 个答案:

答案 0 :(得分:1)

您可以启动所有需要使用某些前缀修饰的方法,然后使用以下内容:

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也是对象,因此您可以更改它并将其传递给另一个函数。

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()

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

x = Xobject()

x.dec_me_1()
x.dec_me_2()

decorate_object(x, decorator)

x.dec_me_1()
x.dec_me_2()

答案 1 :(得分:0)

我确信有一些方法,但主要的主要选项是:

  • 创建一个自定义元类,其中__new__方法遍历属性字典,识别方法并装饰它们。有关Python元类编程的示例,请参阅http://eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example/。缺点:这可能比我们想要进入这里更复杂。
  • 在常规班级__init__方法中执行相同操作。缺点:它只装饰实例方法而不是类或静态方法,而且速度较慢,因为每次创建新实例时它都会运行。
  • 在课外进行:

    class Foo(object):
      def bar(self):
        print 'bar'
    
    for name, ref in vars(Foo):
      if callable(ref): ...
    

    缺点:你只有一次机会做正确的事:在进口时。子类不会被修改。

  • 在类级装饰器中执行。与在课外学习相同的缺点(我认为)。

答案 2 :(得分:0)

在某些时候,你必须明确包裹的内容和不包含的内容。

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

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"