python - 元类 : why method is not inherited from Base class?

标签 python python-3.x metaclass

我正在尝试理解 Python 中的元类黑魔法。 AFAIK,例如,可以使用元类来确保在派生类中实现某些方法,但我有一个问题孙子。看来我需要显式实现所有所需的派生方法,即使没有理由(?)这样做。

看看这个:

~ $ ipython
Python 3.6.5 (default, Apr 14 2018, 13:17:30) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.3.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: class Meta(type):
   ...:     def __new__(cls, name, bases, body):
   ...:         if 'some_method' not in body:
   ...:             raise AttributeError('some_method should be implemented')
   ...:         return super().__new__(cls, name, bases, body)
   ...: 
   ...: class Base(metaclass=Meta):
   ...:     def some_method(self):
   ...:         print('Yay')
   ...: 
   ...: class Derived(Base):
   ...:     pass
   ...: 
   ...: 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-1-51c072cc7909> in <module>()
      9         print('Yay')
     10 
---> 11 class Derived(Base):
     12     pass

<ipython-input-1-51c072cc7909> in __new__(cls, name, bases, body)
      2     def __new__(cls, name, bases, body):
      3         if 'some_method' not in body:
----> 4             raise AttributeError('some_method should be implemented')
      5         return super().__new__(cls, name, bases, body)
      6 

AttributeError: some_method should be implemented

据我了解,这不应该发生,因为 some_method 应该从 Base 类派生,如下所示:

In [3]: class Base:
   ...:     def some_method(self):
   ...:         print('Yay')
   ...: 
   ...: class Derived(Base):
   ...:     pass
   ...: 
   ...: 

In [4]: Derived().some_method()
Yay

这是预期的吗?如果是,您能给我一些如何修复此行为的提示,这样我就不需要重新实现方法吗?

最佳答案

您似乎正在尝试重新发明轮子,即 abc模块及其 @abstractmethod 装饰器。我不确定你为什么要这样做,但如果你这样做,你应该看看 its source (从文档链接)。

您的解决方案检查所需名称是否已在类主体中实现。对于继承的方法则不然,但您似乎知道这一点,所以我不会解释。您想知道的是:您可以做什么?您需要显式检查继承的方法。

abc 的实现方式非常简单:在检查是否所有抽象方法都已实现之前,它会在每个 base 上调用 getattr。 (毕竟,模拟 getattr 对类执行的操作的最佳方法是调用 getattr。)在那里找到的任何内容都不需要出现在正文中。

您的用例(使用静态的单个必需方法,而不是必须从装饰器的输出中获取的动态方法集)甚至更简单:

if (not any(hasattr(base, 'some_method') for base in bases)
    and 'some_method' not in body):

关于python - 元类 : why method is not inherited from Base class?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50320293/

相关文章:

python - 如何使用 python3 将更改模式 json 插入 mysql 中?

python - 如何将我自己的 Meta 类与 SQLAlchemy-Model 一起用作父类

python - 有没有办法在 Python 2.5 中模拟 Python 3 元类的 __prepare__ 特殊方法?

python - 三重继承导致元类冲突......有时

python-3.x - Tkinter - 通过另一个功能更改标签文本

python - 如何删除/usr/local/bin/中的python

python - 如何将字典保存到文件中,并保持良好的格式?

python - 如何解决 ValueError : bad input shape (11, 11)?

android - 如何同时在多个设备上运行 Monkeyrunner 脚本

python - 使用created_at过滤器查询Soundcloud API