微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否可以将属性注册为 abc.abstractmethod 覆盖?

如何解决是否可以将属性注册为 abc.abstractmethod 覆盖?

假设我们有一个类使用组合来“实现”一个方法

'''first.py'''
class SomethingCompletelyDifferent:

    def spam(self) -> str:
        return 'spam'


class Ham:
    '''
    Ham uses the coincidentally same signature of
    SomethingCompletelyDifferent.spam() signature to “implement” self.eggs()
    '''

    def __init__(self) -> None:
        self._scd = SomethingCompletelyDifferent()
        self.eggs = self._scd.spam # THIS line is important!!


print(Ham().eggs()) # use “method” of Ham defined in Ham.__init__

产生预期的输出

>>> import first
spam

现在我们要使用抽象基类抽象出 eggs() 方法

'''second.py'''
import abc


class HamBase(Metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def eggs(self) -> str:
        pass


class Ham(HamBase):

    def eggs(self) -> str:
        return 'eggs'


ham: HamBase = Ham()  # ham object as “abstract” HamBase interface

print(ham.eggs())

一切正常且符合预期

>>> import second
eggs

因为我们使用标准的方式来实现具体的方法

是否可以将两者结合起来并将属性/方法 Ham.eggs() 注册HamBase.eggs() 的显式覆盖?

'''third.py'''
import abc


class SomethingCompletelyDifferent:
    def spam(self) -> str:
        return 'spam'


class HamBase(Metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def eggs(self) -> str:
        pass


class Ham(HamBase):
    def __init__(self) -> None:
        self._scd = SomethingCompletelyDifferent()
        self.eggs = self._scd.spam # like in first.py,but HamBase does not care
        # ← here magic command to tell HamBase that self.eggs overrides?!


ham: HamBase = Ham()  # ham object as “abstract” HamBase interface

print(ham.eggs())

结果

>>> import third
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
  File "/tmp/third.py",line 22,in <module>
    ham: HamBase = Ham()  # ham object as “abstract” HamBase interface
TypeError: Can't instantiate abstract class Ham with abstract method eggs

但应该导致

>>> import third
spam

Python 风格指南表明偏好

  • 显式(在def eggs(self) -> str:中使用second.py

结束

  • 隐式(使用 self.eggs = self._scd.spam 分配的属性作为方法,如 first.pythird.py

尽可能多。

明确地说:是的,我们可以将 Ham.eggs() 实现为

    def eggs(self) -> str:
        return self._scd.spam()

third.py 会起作用。

我的问题是不是关于我们是否应该这样做(根据风格指南显然不是),而是是否可以这样做,如果可以,如何做。

ABC python documentation 中描述的 register() 方法注册子类,而不是为 @abc.abstractmethod 注册,所以这对我也没有帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。