Python 编写一个类修饰符,将修饰符应用于所有方法
我正在尝试编写一个类装饰器,将装饰器应用于所有类的方法:Python 编写一个类修饰符,将修饰符应用于所有方法,python,decorator,Python,Decorator,我正在尝试编写一个类装饰器,将装饰器应用于所有类的方法: import inspect def decorate_func(func): def wrapper(*args, **kwargs): print "before" ret = func(*args, **kwargs) print "after" return ret for attr in "__module__", "__name__", "__
import inspect
def decorate_func(func):
def wrapper(*args, **kwargs):
print "before"
ret = func(*args, **kwargs)
print "after"
return ret
for attr in "__module__", "__name__", "__doc__":
setattr(wrapper, attr, getattr(func, attr))
return wrapper
def decorate_class(cls):
for name, meth in inspect.getmembers(cls, inspect.ismethod):
setattr(cls, name, decorate_func(meth))
return cls
@decorate_class
class MyClass(object):
def __init__(self):
self.a = 10
print "__init__"
def foo(self):
print self.a
@staticmethod
def baz():
print "baz"
@classmethod
def bar(cls):
print "bar"
obj = MyClass()
obj.foo()
obj.baz()
MyClass.baz()
obj.bar()
MyClass.bar()
它几乎可以工作,但是@classmethod
S需要特殊处理:
$ python test.py
before
__init__
after
before
10
after
baz
baz
before
Traceback (most recent call last):
File "test.py", line 44, in <module>
obj.bar()
File "test.py", line 7, in wrapper
ret = func(*args, **kwargs)
TypeError: bar() takes exactly 1 argument (2 given)
inspect.isclass(meth.im_self)
应该告诉您meth
是否是类方法:
def decorate_class(cls):
for name, meth in inspect.getmembers(cls, inspect.ismethod):
if inspect.isclass(meth.im_self):
print '%s is a class method' % name
# TODO
...
return cls
(评论太长)
我冒昧地添加了一个功能,可以指定应该在解决方案中修饰哪些方法:
def class_decorator(*method_names):
def wrapper(cls):
for name, meth in inspect.getmembers(cls):
if name in method_names or len(method_names) == 0:
if inspect.ismethod(meth):
if inspect.isclass(meth.im_self):
# meth is a classmethod
setattr(cls, name, VerifyTokenMethod(meth))
else:
# meth is a regular method
setattr(cls, name, VerifyTokenMethod(meth))
elif inspect.isfunction(meth):
# meth is a staticmethod
setattr(cls, name, VerifyTokenMethod(meth))
return cls
return wrapper
import inspect
import types
import networkx as nx
def override_methods(cls):
for name, meth in inspect.getmembers(cls):
if name in cls.methods_to_override:
setattr(cls, name, cls.DecorateMethod(meth))
return cls
@override_methods
class DiGraph(nx.DiGraph):
methods_to_override = ("add_node", "remove_edge", "add_edge")
class DecorateMethod:
def __init__(self, func):
self.func = func
def __get__(self, obj, cls=None):
def wrapper(*args, **kwargs):
ret = self.func(obj, *args, **kwargs)
obj._dirty = True # This is the attribute I want to update
return ret
return wrapper
def __init__(self):
super().__init__()
self._dirty = True
用法:
@class_decorator('some_method')
class Foo(object):
def some_method(self):
print 'I am decorated'
def another_method(self):
print 'I am NOT decorated'
上述答案并不直接适用于python3。根据其他重要的答案,我能够提出以下解决方案:
def class_decorator(*method_names):
def wrapper(cls):
for name, meth in inspect.getmembers(cls):
if name in method_names or len(method_names) == 0:
if inspect.ismethod(meth):
if inspect.isclass(meth.im_self):
# meth is a classmethod
setattr(cls, name, VerifyTokenMethod(meth))
else:
# meth is a regular method
setattr(cls, name, VerifyTokenMethod(meth))
elif inspect.isfunction(meth):
# meth is a staticmethod
setattr(cls, name, VerifyTokenMethod(meth))
return cls
return wrapper
import inspect
import types
import networkx as nx
def override_methods(cls):
for name, meth in inspect.getmembers(cls):
if name in cls.methods_to_override:
setattr(cls, name, cls.DecorateMethod(meth))
return cls
@override_methods
class DiGraph(nx.DiGraph):
methods_to_override = ("add_node", "remove_edge", "add_edge")
class DecorateMethod:
def __init__(self, func):
self.func = func
def __get__(self, obj, cls=None):
def wrapper(*args, **kwargs):
ret = self.func(obj, *args, **kwargs)
obj._dirty = True # This is the attribute I want to update
return ret
return wrapper
def __init__(self):
super().__init__()
self._dirty = True
现在,只要调用元组
methods\u to\u override
中的方法,就会设置脏标志。当然,其他任何东西也可以放在那里。不必在需要重写其方法的类中包含DecorateMethod
类。但是,由于decorateMethod
使用类的特定属性,因此我更喜欢创建类属性 它成功了,谢谢!我用完整的解决方案更新了我的问题。您的DecoratedClassMethod和DecoratedMethod类完全相同。请编辑以放置正确的解决方案。它们是不同的:DecoratedMethod传递对象实例,而DecoratedClassMethod不传递。它们非常相似,必须能够将它们组合起来以避免重复。按照self.func(cls或obj,*args,**kwargs)的思路思考。我知道这是不一样的,但是一个简单的if
语句和正确的测试将最终避免您使用这两个几乎相同的类。