Skip to main content
 首页 » 编程设计

python之Python 继承的未知属性错误

2025年05月04日16kuangbin

我有一个继承自 Python 抽象类的类

class MyAbstractClass(): 
    __Var1 = 0 
 
    def __init__(self): 
        pass 
 
class MySubClass(MyAbstractClass): 
    def __init__(self): 
        MyAbstractClass.__init__(self) 
 
    def MyFunc(self): 
        print self.__Var1 

出现以下错误:

AttributeError: MySubClass instance has no attribute '_MySubClass__Var1' 

值得注意的是,这两个类位于单独的文件中。

我四处搜索,大多数建议是将我的代码从使用“super()”更改为父项的显式名称。但是,我仍然收到此错误。

知道怎么回事吗?

请您参考如下方法:

你看到的是name mangling .以双下划线开头的名称以特殊方式处理,以避免子类中的名称冲突。

基本上,只要你在类中有一个 __some_name 属性,它就会自动重命名为 _YourClass__some_name 以避免在继承时发生名称冲突。

您可以使用 dir() 进行检查功能:

>>> class MyClass(object): 
...     __var = 1 
...  
>>> dir(MyClass) 
['_MyClass__var', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] 

请注意列表如何不包含__var,而是包含_MyClass__var。

解决方法很简单:不要使用以双下划线开头的变量名。如果您想将变量标记为私有(private),约定是使用单个下划线。

我想再次强调,名称重整的主要目的是避免与子类的命名空间冲突:

>>> class MyClass(object): 
...     def __init__(self, val): 
...             self._value = val 
...  
>>> class MySubclass(object): 
...     def __init__(self, val): 
...             super(MyClass, self).__init__(val) 
...             self._value = val ** 2  #this hides the base class attribute! 
...  

请注意,如果基类来自第三方库,则您无法知道定义了哪些私有(private)属性,因为它们不是 API 的一部分。检查 dir 只会提示您使用了哪个名称,但由于它们是实现细节,因此可以在不另行通知的情况下更改。

您不应该使用它来将属性“标记”为私有(private)。 python 约定 以单个下划线开头的属性是私有(private)的。

在相关主题中,名称开头和末尾都带有双下划线的 __something__ 形式的名称也被特殊处理。其中一些实现了 special methods因此你应该永远不要使用这种标识符。