我一直在研究这个并找到了两个解决方案。使用装饰器更改类并创建委托者,或使用委托者的描述符。我从第一个开始,然后发展到我更喜欢的第二个,所以我将从它开始。两者都可以在这里找到:https://gist.github.com/dhilst/7435a09b4419da349bb4cc4ae855a451 with doctests :)
-- 编辑--
对于任何感兴趣的人,我将其设为图书馆:https://pypi.org/project/delegateto/
gist 实现中存在错误,人们在 github 上对此做出了贡献,pypi 项目已更新,gist 没有。我强烈推荐你使用 pypi 版本。
使用描述符
描述符是可以获取和设置的东西。在这种情况下,我们对描述符的可获取能力感兴趣。像这样定义的委托描述符
class DelegateTo:
def __init__(self, to, method=None):
self.to = to
self.method = method
def __get__(self, obj, objecttype):
if self.method is not None:
return getattr(getattr(obj, self.to), self.method)
for method, v in obj.__class__.__dict__.items():
if v is self:
self.method = method
return getattr(getattr(obj, self.to), method)
而且是这样使用的
class Foo:
upper = DelegateTo('v')
__len__ = DelegateTo('l')
__iter__ = DelegateTo('l')
def __init__(self, v, l):
self.v = v
self.l = l
要调用描述符,只需调用方法Foo('hello').upper()。魔术方法也有效len(Foo('', [1,2,3,4])) 返回 4。上面的 gist 链接具有更强大的实现,但基础是相同的。
使用装饰器
每当您需要以重复的方式更改类行为时,装饰器都是候选者。在这种情况下,装饰器将在类中调用setattr 来创建委托。
def delegate(to, *methods):
def dec(klass):
def create_delegator(method):
def delegator(self, *args, **kwargs):
obj = getattr(self, to)
m = getattr(obj, method)
return m(*args, **kwargs)
return delegator
for m in methods:
setattr(klass, m, create_delegator(m))
return klass
return dec
用法也很简单,只要装饰类,想多少次就行。装饰器将就地修改类,因此返回相同的类。
这是一个用法
@delegate('v', 'upper', 'lower')
class Foo:
def __init__(self, v):
self.v = v
并且委托方法的调用也是透明的Foo('hello').upper()。我更喜欢第二个,因为它对我来说似乎更惯用。装饰器具有支持多种方法的优势,但这也可以在描述符表单上实现。
再次,我真的建议您查看要点:https://gist.github.com/dhilst/7435a09b4419da349bb4cc4ae855a451 文档字符串中有大量示例。只需修改它们并执行脚本即可。
-- 编辑--
对于任何感兴趣的人,我把它做成一个 pip 包https://pypi.org/project/delegateto/
-- 编辑--
gist 实现中存在错误,人们在 github 上对此做出了贡献,pypi 项目已更新,gist 没有。我强烈推荐你使用 pypi 版本。
问候