gpt4 book ai didi

python - 扩展python abc类的类的自动委托(delegate)

转载 作者:行者123 更新时间:2023-12-01 00:35:47 25 4
gpt4 key购买 nike

如果某个类扩展了 abc 类(抽象基类),那么除非我定义所有抽象方法,否则我无法实例化它。但通常在实现装饰器模式时,我只想定义一些抽象方法,而其他方法 - 只是委托(delegate)给装饰对象。这该怎么做?

例如,我想让以下代码工作:

from abc import ABCMeta, abstractmethod


class IElement(object):
__metaclass__ = ABCMeta

@abstractmethod
def click(self):
return

@abstractmethod
def hover(self):
return

# ... more IElement's abstractmethods...


class StandardElement(IElement):

def click(self):
return "click"

def hover(self):
return "hover"

# ... more implemented IElement's methods...


class MyElement(IElement):
def __init__(self, standard_element):
self._standard_element = standard_element
delegate(IElement, standard_element)

def click(self):
return "my click"


assert MyElement(StandardElement()).click() == 'my click'
assert MyElement(StandardElement()).hover() == 'click'

代替
from abc import ABCMeta, abstractmethod


class IElement(object):
__metaclass__ = ABCMeta

@abstractmethod
def click(self):
return

@abstractmethod
def hover(self):
return

# ... more IElement's abstractmethods...


class StandardElement(IElement):

def click(self):
return "click"

def hover(self):
return "hover"

# ... more implemented IElement's methods...


class MyElement(IElement):
def __init__(self, standard_element):
self._standard_element = standard_element

def click(self):
return "my click"

def hover(self):
return self._standard_element.hover()

# ... more manually delegated IElement's methods to self._standard_element object, aggregated in initialiser...


assert MyElement(StandardElement()).click() == 'my click'
assert MyElement(StandardElement()).hover() == 'click'

为此,我需要实现 delegate上面例子中的方法。如何实现?也可以考虑为扩展 abc 类的类提供自动委托(delegate)的一些其他方法。

附言
请不要在这里建议我继承 ( class MyElement(StandardElement)) 作为解决方案...上面提供的代码只是一个示例。在我的真实案例中,MyElement 与 StandardElement 相比完全不同。不过,我必须使 MyElement 与 StandardElement 兼容,因为有时有人应该使用 MyElement 而不是 StandardElement。我真的需要在这里实现“有”关系,而不是"is"。

最佳答案

默认情况下,没有自动方式来执行您想要的委派。委派并不是抽象类的显式部分,所以这并不奇怪。但是,您可以编写自己的委托(delegate)元类,为您添加缺少的方法:

def _make_delegator_method(name):
def delegator(self, *args, **kwargs):
return getattr(self._delegate, name)(*args, **kwargs)
return delegator

class DelegatingMeta(ABCMeta):
def __new__(meta, name, bases, dct):
abstract_method_names = frozenset.union(*(base.__abstractmethods__
for base in bases))
for name in abstract_method_names:
if name not in dct:
dct[name] = _make_delegator_method(name)

return super(DelegatingMeta, meta).__new__(meta, name, bases, dct)

委托(delegate)方法是在一个单独的函数中创建的,因为我们需要一个命名空间,其中 name创建函数后不会更改。在 Python 3 中,您可以在 __new__ 中执行所有操作。通过给出 delegator 的方法具有默认值的仅关键字参数,但 Python 2 中没有仅关键字参数,因此对您不起作用。

下面是你如何使用它:
class MyElement(IElement):
__metaclass__ = DelegatingMeta

def __init__(self, standard_element):
self._delegate = standard_element

def click(self):
return "my click"

分配给 self._delegate设置元类创建的方法将使用的对象。如果你愿意,你可以把它做成某种方法,但这似乎是最简单的方法。

关于python - 扩展python abc类的类的自动委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41309627/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com