我正在寻找一种减少样板装饰的方法。我们有很多使用@decorate的类。例如:

class MyClass(Base):
     @decorate
     def fun1(self):
         pass
     @decorate
     def fun2(self):
         pass
     def fun3(self):
         pass

我想这样做,默认情况下装饰器在那里,除非有人另外指定。

我使用此代码进行自动包装
from functools import wraps

def myDecorator(func):
    @wraps(func)
    def decorator(self, *args, **kwargs):
        try:
            print 'enter'
            ret = func(self, *args, **kwargs)
            print 'leave'
        except:
            print 'exception'
            ret = None

        return ret

    return decorator

class TestDecorateAllMeta(type):
    def __new__(cls, name, bases, local):
        for attr in local:
            value = local[attr]
            if callable(value):
                local[attr] = myDecorator(value)
        return type.__new__(cls, name, bases, local)

class TestClass(object):
    __metaclass__ = TestDecorateAllMeta

    def test_print2(self, val):
        print val

    def test_print(self, val):
        print val

c = TestClass()
c.test_print1("print 1")
c.test_print2("print 2")

我的问题是:
  • 是否有更好的方法来实现自动装饰?
  • 我该如何覆盖?

  • 理想情况下,我的最终解决方案应为:
    class TestClass(object):
        __metaclass__ = TestDecorateAllMeta
    
        def autowrap(self):
            print("Auto wrap")
    
        @dont_decorate
        def test_dont_decorate(self, val):
            print val
    

    编辑

    要讲以下评论之一,因为类是可调用的,而不是在做
    if callable(value):
    

    它应显示为:
    if isinstance(value,types.FunctionType)
    

    最佳答案

    与其让类的用户指定__metaclass__属性,不如让它们从定义它的基类派生。无需不必要地暴露管道。

    除此之外,看起来还不错。可以通过在原始函数上设置一个属性来实现@dont_decorate函数装饰器,您的类装饰器随后会检测到该属性并跳过该装饰(如果存在)。

    def dont_decorate(func):
        func._dont_decorate = True
        return func
    

    然后在您的元类中,现在您已经在其中放置了if callable(value):行:
    if callable(value) and not hasttr(value, "_dont_decorate"):
    

    顺便说一句,类是可调用的,因此,如果您不希望装饰内部类,则可能应使用isinstance()而不是callable()检查函数。

    如果您对更明确的替代方法感兴趣,则可以看看this recent question,其中有人希望使用类装饰器做基本相同的事情。不幸的是,这要复杂得多,因为在装饰者看到它们之前,这些方法已经被包装了。

    10-02 01:29
    查看更多