【问题标题】:python apply decorator to every method in a class without inspectpython将装饰器应用于类中的每个方法而不进行检查
【发布时间】:2012-08-07 04:34:42
【问题描述】:

稍微修改Applying python decorators to methods in a class 的答案,可以将装饰器应用于类中的每个方法。如果没有检查模块,有什么方法可以做到这一点?我一直在尝试使用元类和修改 __getattribute__ 来实现这一点,但我不断得到无限递归。从How is the __getattribute__ method used? 开始,这可以使用 object.__getattribute__(self, name) 在普通类中修复。元类有什么等价物吗?

【问题讨论】:

    标签: python class decorator metaclass


    【解决方案1】:

    定义一个元类,然后在类定义的末尾应用装饰器。

    class Classname:
       def foo(self): pass
    
    for name, fn in inspect.getmembers(Classname):
        if isinstance(fn, types.UnboundMethodType):
            setattr(Classname, name, decorator(fn))
    

    对于 Python 3,只需将 types.UnboundMethodType 替换为 types.FunctionType.

    但如果你真的不想使用检查,那么你可以这样做

    import types
    
    class DecoMeta(type):
       def __new__(cls, name, bases, attrs):
    
          for attr_name, attr_value in attrs.iteritems():
             if isinstance(attr_value, types.FunctionType):
                attrs[attr_name] = cls.deco(attr_value)
    
          return super(DecoMeta, cls).__new__(cls, name, bases, attrs)
    
       @classmethod
       def deco(cls, func):
          def wrapper(*args, **kwargs):
             print "before",func.func_name
             func(*args, **kwargs)
             print "after",func.func_name
          return wrapper
    
    class MyKlass(object):
       __metaclass__ = DecoMeta
    
       def func1(self): 
          pass
    
    MyKlass().func1()
    

    输出:

    func1 之前
    func1 之后

    注意:不会修饰staticmethod和classmethod

    【讨论】:

    • 你确定它不会装饰静态方法吗?因为在问了这个问题之后,我发现了 __new__ 并在 staticmethod 的工作原理上写了一些非常相似的东西。
    猜你喜欢
    • 1970-01-01
    • 2016-01-03
    • 2016-07-24
    • 2016-03-17
    • 1970-01-01
    • 2021-04-20
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多