我有一个class1,需要继承2个不同的元类,即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个不同的meta是错误的。
我改变了metclass的加载方式(尝试了几次),我得到了
TypeError:调用元类基础时出错
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
我没主意了...
EDITED 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
dir(mainClass)
没有['__abstractmethods__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry']
救命!
EDITED 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只会在尝试实例化类时抱怨类具有抽象方法,而不是在创建类时抱怨。这是因为该类的元类仍为ABCMeta
(或其子类型),因此允许使用抽象方法。
要获得所需的内容,您需要编写自己的元类,当它发现__abstractmethods__
不为空时会引发错误。这样,您必须明确声明何时不再允许类使用抽象方法。
from abc import ABCMeta, abstractmethod
class YourMeta(type):
def __init__(self, *args, **kwargs):
super(YourMeta, self).__init__(*args, **kwargs)
print "YourMeta.__init__"
def __new__(cls, *args, **kwargs):
newcls = super(YourMeta, cls).__new__(cls, *args, **kwargs)
print "YourMeta.__new__"
return newcls
class ConcreteClassMeta(ABCMeta):
def __init__(self, *args, **kwargs):
super(ConcreteClassMeta, self).__init__(*args, **kwargs)
if self.__abstractmethods__:
raise TypeError("{} has not implemented abstract methods {}".format(
self.__name__, ", ".join(self.__abstractmethods__)))
class CombinedMeta(ConcreteClassMeta, YourMeta):
pass
class AbstractBase(object):
__metaclass__ = ABCMeta
@abstractmethod
def f(self):
raise NotImplemented
try:
class ConcreteClass(AbstractBase):
__metaclass__ = CombinedMeta
except TypeError as e:
print "Couldn't create class --", e
class ConcreteClass(AbstractBase):
__metaclass__ = CombinedMeta
def f(self):
print "ConcreteClass.f"
assert hasattr(ConcreteClass, "__abstractmethods__")
c = ConcreteClass()
c.f()
哪个输出:
YourMeta.__new__
YourMeta.__init__
Couldn't create class -- ConcreteClass has not implemented abstract methods f
YourMeta.__new__
YourMeta.__init__
ConcreteClass.f
关于python - 1个类继承2个不同的元类(abcmeta和用户定义的元),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31379485/