继承结构中添加抽象类层后为何无法访问基类类属性?
类属性继承失效问题解析
问题场景
正常运行的代码
class base(object): my_dict = {} class inherited(base): def __init__(self): new_dict = inherited.my_dict.copy() i = inherited()
插入抽象类后出错的代码
from abc import ABCMeta, abstractmethod from future.utils import with_metaclass class base: my_dict = {} class abstract_base(with_metaclass(ABCMeta, object), base): @abstractmethod def func(self): pass class inherited(abstract_base): def __init__(self): new_dict = inherited.my_dict.copy() def func(self): print("here") i = inherited()
报错信息
Traceback (most recent call last): File "test.py", line 18, in <module> i = inherited() File "test.py", line 14, in __init__ new_dict = inherited.my_dict AttributeError: type object 'inherited' has no attribute 'my_dict'
问题核心:inherited继承自abstract_base,abstract_base声明继承base,但为何间接继承的类属性my_dict无法访问?
原因解析
问题出在abstract_base的定义方式上:
class abstract_base(with_metaclass(ABCMeta, object), base):
with_metaclass的正确用法是第一个参数指定元类,第二个参数指定要继承的基类,它会返回一个已经应用了目标元类的新类。你这里把with_metaclass(ABCMeta, object)和base并列作为父类,这种写法完全错误——with_metaclass(ABCMeta, object)已经生成了一个继承自object的类,再把base作为另一个父类后,Python的*方法解析顺序(MRO)*并没有正确将base的属性合并到abstract_base中,导致abstract_base实际上并没有继承到base的my_dict属性,子类inherited自然也访问不到。
修复方法
正确的写法是把base作为with_metaclass的第二个参数,让元类直接应用在base的子类上:
class abstract_base(with_metaclass(ABCMeta, base)): @abstractmethod def func(self): pass
这样abstract_base就会正确继承base的所有类属性,inherited也能正常访问my_dict了。
内容的提问来源于stack exchange,提问作者web4141
相关产品推荐
相关产品推荐

