我有一个继承自 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因此你应该永远不要使用这种标识符。
