使用装饰器动态地将方法添加到类中
Posted
技术标签:
【中文标题】使用装饰器动态地将方法添加到类中【英文标题】:add method to a class dynamically with decorator 【发布时间】:2012-03-15 16:03:25 【问题描述】:我会动态地将方法添加到class
...函数名也将动态传递。
我该怎么办?我是这样尝试的
def decor(*var):
def onDecorator(aClass):
class onInstance:
def __init__(self,*args,**kargs):
setter=var
aClass.setter = self.flam
self.wrapped = aClass(*args,**kargs)
def __getattr__(self,attr):
return getattr(self.wrapped,attr)
def __setattr__(self,attr,value):
if attr == 'wrapped':
self.__dict__[attr]=value
else:
setattr(self.wrapped,attr,value)
def flam(self,*args):
self.__setattr__('dimension',len(args[0]))
return onInstance
return onDecorator
但如果我这样做:
print(aClass.__dict__)
我有
'setter': <bound method onInstance.flam of <__main__.onInstance object at 0x522270>>
而不是var
:.....
我有这门课:
class D:
def __init__(self, data):
self.data = data
self.dimension = len(self.data)
我会打电话给:
D.name()
已经回复self.dimension
,但我不知道提前name
【问题讨论】:
显示您希望用于将方法附加到类的代码示例。我不知道您如何拥有要附加的方法,但没有任何名称。我也不知道如果该类最初不是使用该方法设计的,那么您希望该方法如何有意义地附加到该类。 多年后,但展示了一个很好且简单的解决方案:medium.com/@mgarod/… 【参考方案1】:这是我的装饰器
def decorator(name):
def wrapper(K):
setattr(K, name, eval(name))
return K
return wrapper
这是一个示例方法
def myfunc(self):
print "Istance class: ", self
这是一个装饰类
@decorator("myfunc")
class Klass:
pass
我希望这是有用的,你需要什么:)
【讨论】:
【参考方案2】:这是一个简化的 py3 解决方案
class A(object):
def a(self):
print('a')
def add_b(cls):
def b(self):
print('b')
setattr(cls, 'b', b)
return cls
@add_b
class C(A):
pass
C().b() # 'b'
【讨论】:
这是这里所有解决方案中最优雅的【参考方案3】:def add_method(cls):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
setattr(cls, func.__name__, wrapper)
return func
return decorator
现在你可以像这样使用它了:
class Foo:
pass
@add_method(Foo)
def bar(self, parameter1):
pass # Do something where self is a class instance
只要记住在要添加到类的函数中有 self 参数。
【讨论】:
【参考方案4】:def dec(cls):
setattr(cls, 'c', 0) # add atr counter to CLS
def __init__(self):
cls.c += 1 # +1 to CLS, not self!
def get_c(self=None):
return cls.c # get current value from CLS
setattr(cls, '__init__', __init__) # add new __init__ IT WILL OVERWRITE original __init__
setattr(cls, 'get_c', get_c) # add new method
return cls
@dec
class A:
pass
print(A.c) # 0
user, _, _ = A(), A(), A()
user.get_c() # 3
如果您想保存原始 init 并向 def init
添加新值def __init__(self):
cls.c += 1 # +1 to CLS, not self!
cls.__init__
【讨论】:
以上是关于使用装饰器动态地将方法添加到类中的主要内容,如果未能解决你的问题,请参考以下文章