- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有一个 class1 需要从两个不同的元类继承,即 Meta1 和 abc.ABCMeta
当前实现:
Meta1 的实现:
class Meta1(type):
def __new__(cls, classname, parent, attr):
new_class = type.__new__(cls, classname, parent, attr)
return super(Meta1, cls).__new__(cls, classname, parent, attr)
class1Abstract 的实现
class class1Abstract(object):
__metaclass__ = Meta1
__metaclass__ = abc.ABCMeta
主类的实现
class mainClass(class1Abstract):
# do abstract method stuff
我知道两次实现 2 个不同的元数据是错误的。
我改变了加载metclass的方式(几次尝试),我明白了TypeError:调用元类库时出错
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
我的想法用完了......
已编辑 1
我尝试了这个解决方案,它可以工作,但 mainClass 不是 class1Abstract 的实例
print issubclass(mainClass, class1Abstract) # true
print isinstance(mainClass, class1Abstract) # false
class1Abstract的实现
class TestMeta(Meta1):
pass
class AbcMeta(object):
__metaclass__ = abc.ABCMeta
pass
class CombineMeta(AbcMeta, TestMeta):
pass
class class1Abstract(object):
__metaclass__ = CombineMeta
@abc.abstractmethod
def do_shared_stuff(self):
pass
@abc.abstractmethod
def test_method(self):
''' test method '''
mainClass的实现
class mainClass(class1Abstract):
def do_shared_stuff(self):
print issubclass(mainClass, class1Abstract) # True
print isinstance(mainClass, class1Abstract) # False
由于 mainClass 继承自一个抽象类,python 应该提示 test_method 没有在 mainClass 中实现。但它并没有提示什么,因为 print isinstance(mainClass, class1Abstract) # False
目录(mainClass)
没有
['__abstractmethods__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry']
帮助!
已编辑 2
class1Abstract的实现
CombineMeta = type("CombineMeta", (abc.ABCMeta, Meta1), {})
class class1Abstract(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def do_shared_stuff(self):
pass
@abc.abstractmethod
def test_method(self):
''' test method '''
mainClass的实现
class mainClass(class1Abstract):
__metaclass__ = CombineMeta
def do_shared_stuff(self):
print issubclass(mainClass, class1Abstract) # True
print isinstance(mainClass, class1Abstract) # False
dir(mainClass)
现在有了 abstractmethod 的魔法方法
['__abstractmethods__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry', 'do_shared_stuff', 'test_method']
但是 python 没有警告 test_method 没有被实例化
帮助!
最佳答案
在 Python 中,每个类只能有一个元类,而不是很多。但是,可以通过混合这些元类执行的操作来实现类似的行为(例如,如果它有多个元类)。
让我们从简单的开始。我们自己的元类,只是给类添加新属性:
class SampleMetaClass(type):
"""Sample metaclass: adds `sample` attribute to the class"""
def __new__(cls, clsname, bases, dct):
dct['sample'] = 'this a sample class attribute'
return super(SampleMetaClass, cls).__new__(cls, clsname, bases, dct)
class MyClass(object):
__metaclass__ = SampleMetaClass
print("SampleMetaClass was mixed in!" if 'sample' in MyClass.__dict__ else "We've had a problem here")
这会打印“SampleMetaClass was mixed in!”,所以我们知道我们的基本元类工作正常。
现在,另一方面,我们想要一个抽象类,最简单的是:
from abc import ABCMeta, abstractmethod
class AbstractClass(object):
__metaclass__ = ABCMeta
@abstractmethod
def implement_me(self):
pass
class IncompleteImplementor(AbstractClass):
pass
class MainClass(AbstractClass):
def implement_me(self):
return "correct implementation in `MainClass`"
try:
IncompleteImplementor()
except TypeError as terr:
print("missing implementation in `IncompleteImplementor`")
MainClass().implement_me()
这会打印“IncompleteImplementor
中缺少的实现”,然后是“MainClass
中的正确实现”。因此,抽象类也可以正常工作。
现在,我们有 2 个简单的实现,我们需要将两个元类的行为混合在一起。这里有多种选择。
选项 1 - 子类化
可以将 SampleMetaClass
实现为 ABCMeta
的子类 - 元类也是类,可以继承它们!
class SampleMetaABC(ABCMeta):
"""Same as SampleMetaClass, but also inherits ABCMeta behaviour"""
def __new__(cls, clsname, bases, dct):
dct['sample'] = 'this a sample class attribute'
return super(SampleMetaABC, cls).__new__(cls, clsname, bases, dct)
现在,我们更改 AbstractClass
定义中的元类:
class AbstractClass(object):
__metaclass__ = SampleMetaABC
@abstractmethod
def implement_me(self):
pass
# IncompleteImplementor and MainClass implementation is the same, but make sure to redeclare them if you use same interpreter from the previous test
然后再次运行我们的两个测试:
try:
IncompleteImplementor()
except TypeError as terr:
print("missing implementation in `IncompleteImplementor`")
MainClass().implement_me()
print("sample was added!" if 'sample' in IncompleteImplementor.__dict__ else "We've had a problem here")
print("sample was added!" if 'sample' in MainClass.__dict__ else "We've had a problem here")
这仍然会打印出 IncompleteImplementor
没有正确实现,MainClass
是,并且两者现在都具有 sample
类级属性添加。这里需要注意的是,元类的 Sample
部分也成功地应用于 IncompleteImplementor
(好吧,没有理由不这样做)。
正如预期的那样,isinstance
和 issubclass
仍然可以正常工作:
print(issubclass(MainClass, AbstractClass)) # True, inheriting from AbtractClass
print(isinstance(MainClass, AbstractClass)) # False as expected - AbstractClass is a base class, not a metaclass
print(isinstance(MainClass(), AbstractClass)) # True, now created an instance here
选项 2 - 编写元类
其实问题本身就有这个选项,只需要一个小修复即可。将新的元类声明为几个更简单的元类的组合,以混合它们的行为:
SampleMetaWithAbcMixin = type('SampleMetaWithAbcMixin', (ABCMeta, SampleMetaClass), {})
如前所述,更改 AbstractClass
的元类(同样,IncompleteImplementor
和 MainClass
不会更改,但如果在同一个解释器):
class AbstractClass(object):
__metaclass__ = SampleMetaWithAbcMixin
@abstractmethod
def implement_me(self):
pass
从这里开始,运行相同的测试应该会产生相同的结果:ABCMeta
仍然有效并确保实现了 @abstractmethod
-s,SampleMetaClass
添加sample
属性。
我个人更喜欢后一种选择,原因与我通常更喜欢组合而不是继承的原因相同:在多个(元)类之间最终需要的组合越多 - 组合就越简单。
有关元类的更多信息
最后,我读过的关于元类的最佳解释是这样的答案: What is a metaclass in Python?
关于python - 1 个类继承 2 个不同的元类(abcmeta 和用户定义的元),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31379485/
通常,为了子类化一个类,我会做类似的事情 class Subby(Parenty): def __init__(self): Parenty.__init__(self) 但是
ABCMeta的register方法有什么用? https://docs.python.org/3/library/abc.html 似乎如果我有一个抽象基类 ABC,比如 Animal,我可以使用
以下dataclass : from abc import ABC from collections.abc import Mapping from dataclasses import datacl
我在网上看代码的时候遇到过以下使用抽象类的情况: from abc import abstractmethod,ABCMeta class Generator(object,metaclass=ABC
我在网上看代码的时候遇到过以下使用抽象类的情况: from abc import abstractmethod,ABCMeta class Generator(object,metaclass=ABC
我想实现一个元类来包装方法以记录附加信息。但我还需要有 abstractmethods。我试图扩展 ABCMeta 但它似乎没有强制执行 @abstractmethod 装饰器: import typ
我有一个类似于下面的目录结构: . ├── main.py ├── model.py └── models ├── __init__.py ├── model_a.py └──
我对 python 3.8 和 mypy 协同工作的方式有疑问。考虑这个代码: from collections.abc import Callable def feeder(get_next_ite
我得到了一个使用 python 的 abc 包的示例代码。我使用 pip 在笔记本电脑中安装了 abc。在 PATH 中正确设置了包文件夹的路径。 我得到的示例代码是: '从 abc 导入 ABC,抽
考虑这段代码 from abc import ABCMeta, abstractmethod class C(): @abstractmethod def my_abstract_me
我有以下代码来比较基类的当前(空)所需功能的实现与其子类,子类必须以某种不同的方式实现它们,以便在运行时被认为是可接受的。如果不使用 metaclass=ABCMeta 并在这些基类方法上实现 @ab
这个问题在这里已经有了答案: Create an abstract Enum class (3 个答案) 关闭 3 年前。 简单示例 目标是通过从 abc.ABCMeta 和 enum.EnumMe
在 Python 3.4+ 中,我们可以这样做 class Foo(abc.ABC): ... 或者我们可以做 class Foo(metaclass=abc.ABCMeta): ..
我在 python 中看到了两种定义抽象类的方法.有什么区别,分别有哪些使用场景? from abc import ABCMeta, abstractmethod class AbstactClass
我正在通过标记我的几个函数来试用 Python 3.5 的输入模块。 虽然我在 PyCharm 中收到警告,但我有一个返回列表的函数。 警告内容如下: Class 'ABCMeta' does not
我有一个 class1 需要从两个不同的元类继承,即 Meta1 和 abc.ABCMeta 当前实现: Meta1 的实现: class Meta1(type): def __new__(c
我一直在用 python 中的 abc 模块进行一些试验。啦啦啦 >>> import abc 在正常情况下,如果 ABC 类包含未实现的 abstractmethod,您希望它不会被实例化。你知道如
我在 Linux 上使用 PyDev 编写代码时遇到了这个奇怪的错误。即使像这样的简单代码也会产生错误 print 'Hello World' 错误在这里 True Traceback (most r
我将 Python 3.7.3 与 PyCharm 结合使用。当我尝试将 abc 包导入到我的项目中时,我收到此错误,然后是 Python 意外退出 警告对话框: Fatal Python error
在 Python 中,当尝试使用 irc-8.1.1 的示例程序 irccat2.py 时,出现此错误。我无法在网上的任何地方找到它的记录。有谁知道这意味着什么,我该如何解决?谢谢。 Tracebac
我是一名优秀的程序员,十分优秀!