如何在Python中找到修饰方法的包含类
我正在尝试实现一个装饰器类,它将装饰其他类中的方法。但是,我需要一个类,该类保存decorator中可用的修饰方法。我好像到处都找不到 下面是一个例子:如何在Python中找到修饰方法的包含类,python,Python,我正在尝试实现一个装饰器类,它将装饰其他类中的方法。但是,我需要一个类,该类保存decorator中可用的修饰方法。我好像到处都找不到 下面是一个例子: class my_decorator(object): def __init__(self, arg1, arg2): print(self.__class__.__name__ + ".__init__") self.arg1 = arg1 self.arg2 = arg2 def __call__(sel
class my_decorator(object):
def __init__(self, arg1, arg2):
print(self.__class__.__name__ + ".__init__")
self.arg1 = arg1
self.arg2 = arg2
def __call__(self, my_callable):
print(self.__class__.__name__ + ".__call__")
print(type(my_callable))
self.my_callable = my_callable
# self.my_callable_method_class = ?where to get this?
def function_wrapper(*args, **kwargs):
print(self.__class__.__name__ + ".function_wrapper")
print(self.arg1)
self.my_callable.__call__(*args, **kwargs)
print(self.arg2)
return function_wrapper
class MyClass(object):
@my_decorator(arg1="one", arg2="two")
def decorated_method(self):
print(self.__class__.__name__ + ".decorated_method")
print(type(self.decorated_method))
print("hello")
m = MyClass()
m.decorated_method()
将打印出以下内容:
my_decorator.__init__
my_decorator.__call__
<type 'function'>
my_decorator.function_wrapper
one
MyClass.decorated_method
<type 'instancemethod'>
hello
two
但我不想这样做,因为这是多余的,不好
或者我应该以其他方式实现这一点?我基本上需要装饰器的几个参数,我需要装饰器中装饰方法的类。您可以装饰类:
并使用外部装饰器将类参数发送到内部
您的任何建议都无法工作,因为它们需要在类存在之前访问该类。定义类时,首先在其主体内执行代码(定义函数等),然后将生成的作用域作为类的
\uuuuu dict\uuuu
分配给该类。因此,在定义decordent\u方法时,MyClass
还不存在。如果将decorator返回的对象设为a,则可以钩住属性查找以返回链接方法和类(或实例)的其他对象
对于方法样式描述符,您只需要实现\uuu get\uu
方法。在类上查找方法时,以下两个是等效的:
m = MyClass.decorated_method
# It will actually get the object from any parent class too. But this will do for a simple example
m = MyClass.__dict__['decorated_method'].__get__(MyClass)
instance = MyClass()
m = instance.decorated_method
m = type(instance).__dict__['decorated_method'].__get__(instance, type(instance))
例如,以下内容是等效的:
m = MyClass.decorated_method
# It will actually get the object from any parent class too. But this will do for a simple example
m = MyClass.__dict__['decorated_method'].__get__(MyClass)
instance = MyClass()
m = instance.decorated_method
m = type(instance).__dict__['decorated_method'].__get__(instance, type(instance))
因此表达式instance.decordent\u方法(…)
实际上调用了\uuuu get\uuu
方法返回的对象。这与允许简单函数对象转变为绑定方法对象(添加隐式self
参数)的过程相同
创建此可调用项时,您应该拥有所需的所有信息。这里有一个修订版,可以使用
# This holds all called method_decorators
global_method_decorator_list = []
class class_decorator(object):
def __init__(self, arg1, arg2):
print(self.__class__.__name__ + ".__init__")
self.arg1 = arg1
self.arg2 = arg2
def __call__(self, my_class):
print(self.__class__.__name__ + ".__call__")
print(repr(my_class))
print(my_class.__name__)
self.cls = my_class
class_decorators[my_class] = self
self.my_class = my_class
# Call each method decorator's second_init()
for d in global_method_decorator_list:
d._method_decorator_.second_init(self, my_class)
def wrapper(*args, **kwargs):
print(self.__class__.__name__ + ".wrapper")
print(self.arg1)
retval = self.my_class.__call__(*args, **kwargs)
print(self.arg2)
return retval
return wrapper
class method_decorator(object):
def __init__(self, arg1, arg2):
print(self.__class__.__name__ + ".__init__")
self.arg1 = arg1
self.arg2 = arg2
def __call__(self, my_callable):
print(self.__class__.__name__ + ".__call__")
print(repr(my_callable))
self.my_callable = my_callable
# Mark the callable and add to global list
my_callable._method_decorator_ = self
global_method_decorator_list.append(my_callable)
def wrapper(*args, **kwargs):
print(self.__class__.__name__ + ".wrapper")
print(self.arg1)
retval=self.my_callable.__call__(*args, **kwargs)
print(self.arg2)
return retval
return wrapper
def second_init(self, the_class_decorator, the_class):
print(self.__class__.__name__ + ".second_init")
print("The Class: " + repr(the_class))**
@class_decorator(arg1="One", arg2="Two")
class MyClass(object):
@method_decorator(arg1="one", arg2="two")
def decorated_method(self):
print(self.__class__.__name__ + ".decorated_method")
print(type(self.decorated_method))
print("hello")
m = MyClass()
m.decorated_method()
输出如下所示:
class_decorator.__init__
method_decorator.__init__
method_decorator.__call__
<function decorated_method at 0x3063500>
class_decorator.__call__
<class '__main__.MyClass'>
MyClass
method_decorator.second_init
The Class: <class '__main__.MyClass'>
class_decorator.wrapper
One
Two
method_decorator.wrapper
one
MyClass.decorated_method
<type 'instancemethod'>
hello
two
class\u decorator.\u初始化__
方法\u decorator.\uu init__
方法\u decorator.\u调用__
类装饰器。请呼叫__
类名
方法\u decorator.second\u init
班级:
class_decorator.wrapper
一个
两个
方法\u decorator.wrapper
一
MyClass.u方法
你好
二
不同之处在于,现在该类有一个单独的装饰器。类装饰器的调用将调用每个方法装饰器的“second_init()”方法,并将类传递到那里
值得注意的是,方法_decorator的调用()将在类_decorator的调用之前被调用。您到底什么时候需要类?您可以将内部包装修改为def function\u包装(self,*args,**kwargs)
,并将类作为self.\uuu class\uuu
获取。如果你需要在装饰器之外的类,那么就像KatrieleAlex已经指出的那样,这是非常困难的。这个问题是,我需要在创建第一个实例之前处理这个类。这很公平。然后你可能会想要一个像KatrieleAlex建议的那样标记函数的装饰器,然后从类装饰器或元类构造函数中修复问题。但是如何链接类装饰器和方法装饰器呢?我将有很多类和方法使用相同的装饰器…@my_decorator
应该标记它装饰过的方法,比如给它们一个特殊属性@decoration
应该迭代所有类方法,过滤那些没有特殊属性的类方法,然后依次对每个类方法进行修饰。