Chu*_*uim 7 python reflection instrumentation decorator
我想创建一个Python 类装饰器(*),它能够无缝地包装类可能具有的所有方法类型:实例,类和静态.
这是我现在的代码,其中的部分打破了它:
def wrapItUp(method):
def wrapped(*args, **kwargs):
print "This method call was wrapped!"
return method(*args, **kwargs)
return wrapped
dundersICareAbout = ["__init__", "__str__", "__repr__"]#, "__new__"]
def doICareAboutThisOne(cls, methodName):
return (callable(getattr(cls, methodName))
and (not (methodName.startswith("__") and methodName.endswith("__"))
or methodName in dundersICareAbout))
def classDeco(cls):
myCallables = ((aname, getattr(cls, aname)) for aname in dir(cls) if doICareAboutThisOne(cls, aname))
for name, call in myCallables:
print "*** Decorating: %s.%s(...)" % (cls.__name__, name)
setattr(cls, name, wrapItUp(call))
return cls
@classDeco
class SomeClass(object):
def instanceMethod(self, p):
print "instanceMethod: p =", p
@classmethod
def classMethod(cls, p):
print "classMethod: p =", p
@staticmethod
def staticMethod(p):
print "staticMethod: p =", p
instance = SomeClass()
instance.instanceMethod(1)
#SomeClass.classMethod(2)
#instance.classMethod(2)
#SomeClass.staticMethod(3)
#instance.staticMethod(3)
Run Code Online (Sandbox Code Playgroud)
我有两个问题试图让这项工作:
目前,此代码TypeError根据取消注释的注释片段生成不同的s,例如:
TypeError: unbound method wrapped() must be called with SomeClass instance as first argument (got int instance instead)TypeError: classMethod() takes exactly 2 arguments (3 given)(*):如果你直接装饰方法,同样的问题要简单得多.
因为方法是函数的包装器,所以要在构造类后将装饰器应用于类上的方法,您必须:
im_func。一旦应用了装饰器,就很难区分 aclassmethod和常规方法;@classmethod两种方法都是类型instancemethod。但是,您可以检查该im_self属性并查看它是否为None。如果是这样,那么它是一个常规实例方法;否则它是一个classmethod.
静态方法是简单的函数(@staticmethod装饰器只是阻止应用通常的方法包装器)。所以看起来你不需要为这些做任何特别的事情。
所以基本上你的算法看起来像这样:
types.MethodType?如果是这样,那么它要么是类方法,要么是实例方法。
im_self是None,则它是一个实例方法。通过属性提取底层函数im_func,对其进行修饰,然后重新应用实例方法:meth = types.MethodType(func, None, cls)im_self不是None,则它是一个类方法。通过提取底层函数im_func并对其进行装饰。现在您必须重新应用classmethod装饰器,但您不能,因为它classmethod()不接受类,因此无法指定它将附加到哪个类。相反,您必须使用实例方法装饰器:meth = types.MethodType(func, cls, type)。请注意,type这里是实际的内置,type.types.MethodType那么它是静态方法或其他非绑定可调用方法,因此只需装饰它即可。这些在 Python 3 中有所改变——未绑定的方法是那里的函数,IIRC。无论如何,这可能需要彻底重新考虑。