![](/img/trans.png)
[英]How to make an Abstract Class inherit from another Abstract Class in Python?
[英]How to register classes that inherit from an abstract class in python
我正在創建一個帶有 function 的模塊,該模塊用作已實現類的工廠。 它在元類(我剛剛從這里復制的模式)的幫助下注冊類。
_registry = {}
def register_class(cls):
_registry[cls.__name__] = cls
class Meta(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
register_class(cls)
return cls
def factory(name):
return _registry[name]()
到目前為止,這有效。
現在我的一個特殊性是我正在實現共享很多功能的類,因此我定義了一個抽象基礎 class 來實現大部分共享邏輯,以及大量改進某些特殊性的派生類。 問題是這會導致元類沖突,因為派生類的元類既是ABCmeta
又是Meta
:
from abc import ABC, abstractmethod
_registry = {}
def register_class(cls):
_registry[cls.__name__] = cls
class Meta(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
register_class(cls)
return cls
def factory(name):
return _registry[name]()
class Base(ABC):
pass
class Derived1(Base, metaclass=Meta):
pass
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
我該如何解決這個沖突?
只需將您需要的元類組合成一個合適的派生元類,然后將其用作您的元類。 在這種情況下,jsut 從“ABCMeta”而不是類型派生您的元類:
from abc import ABCMeta
class Meta(ABCMeta):
def __new__(meta, name, bases, class_dict):
cls = super().__new__(meta, name, bases, class_dict)
register_class(cls)
return cls
注意使用super().__new__
而不是type.__new__
的重要性——這是我們的元類能夠與其他元類結合的必要條件(只要它們都不會直接干擾您自己的元類的相同屬性/邏輯)正在處理中)。
因此,如果您需要某些類來使用 ABCMeta,而某些類需要單獨使用您的元類,您可以通過將type.__new__
調用替換為super().__new__
使用您的元類作為 mixin,以根據需要組合 ABCMeta:
from abc import ABCMeta
class Meta(type):
...
class MetaWithAbc(Meta, ABCMeta):
pass
class Base(metaclass=MetaWithAbc):
pass
...
此外,自 Python 3.6 以來,隨着特殊__init_subclass__
方法的引入,對元類的需求已大大減少。 簡單地將 class 添加到注冊表中,在這種情況下,如果您有一個公共基類,則不需要自定義元類:每個子類調用一次__init_subclass__
,因為它是創建的:
from abc import ABC, abstractmethod
_registry = {}
def register_class(cls):
_registry[cls.__name__] = cls
def factory(name):
return _registry[name]()
class Base(ABC):
def __init_subclass__(cls, **kwargs):
# always make it colaborative:
super().__init_subclass__(cls, **kwargs)
register_class(cls)
class Derived1(Base):
pass
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.