如何解决ABC拒绝我的子类,尽管它没有抽象方法
我有一个collections.abc.MutableMapping
子类,该子类通过猴子补丁实现了所需的抽象方法:
from collections.abc import MutableMapping
def make_wrappers(cls,methods = []):
"""This is used to eliminate code repetition,this file contains around 12
classes with similar rewirings of self.method to self.value.method
This approach is used instead of overriding __getattr__ and __getattribute__
because those are bypassed by magic methods like add()
"""
for method in methods:
def wrapper(self,*args,_method=method,**kwargs):
return getattr(self.value,_method)(*args,**kwargs)
setattr(cls,method,wrapper)
class MySubclass(MutableMapping):
def __init__(self,value = None):
value = {} if value is None else value
self.value = value
make_wrappers(
MySubclass,['__delitem__','__getitem__','__iter__','__len__','__setitem__']
)
尝试实例化MySubclass时,出现此错误:
>>> c = MySubclass({'a':a,'b':b})
Traceback (most recent call last):
File "<pyshell#10>",line 1,in <module>
c = MySubclass({'a':1,'b':2})
TypeError: Can't instantiate abstract class MySubclass with abstract methods __delitem__,__getitem__,__iter__,__len__,__setitem__
这仍然有效:
>>> MySubclass.__setitem__
<function make_wrappers.<locals>.wrapper at 0x0000020F76A24AF0>
如何强制实例化?
我知道这些方法有效,因为当我在MySubclass
和collections.abc.MutableMapping
之间放置一层继承时,它们就神奇地做到了!
解决方法
创建ABC
creates a set of missing abstract methods as soon as the class is created。必须清除此内容以允许实例化该类。
>>> # setup as before
>>> MySubclass.__abstractmethods__
frozenset({'__delitem__','__getitem__','__iter__','__len__','__setitem__'})
>>> MySubclass({'a':a,'b':b})
# TypeError: Can't instantiate abstract class MySubclass with abstract methods __delitem__,__getitem__,__iter__,__len__,__setitem__
>>> MySubclass.__abstractmethods__ = frozenset() # clear cache of abstract methods
>>> MySubclass({'a':a,'b':b})
<__main__.MySubclass at 0x1120a9340>
请注意,.__abstractmethods__
不属于Python Data Model或abc
specification的一部分。考虑它的版本和实现特定–始终测试目标版本/实现是否使用它。但是,它应该可以在CPython(Py3.6和Py3.9上的睾丸)和PyPy3(Py3.6上的睾丸)上工作。
可以调整包装器功能,以自动从抽象方法缓存中删除猴子修补的方法。如果修补了所有方法,这将使该类有资格进行实例化。
def make_wrappers(cls,methods = []):
"""This is used to eliminate code repetition,this file contains around 12
classes with similar rewirings of self.method to self.value.method
This approach is used instead of overriding __getattr__ and __getattribute__
because those are bypassed by magic methods like add()
"""
for method in methods:
def wrapper(self,*args,_method=method,**kwargs):
return getattr(self.value,_method)(*args,**kwargs)
setattr(cls,method,wrapper)
cls.__abstractmethods__ = cls.__abstractmethods__.difference(methods)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。