python - 为什么子类访问超类的属性,尽管当该属性被声明为私有时,它有自己的同名属性?
问题描述
我有一个父类Animal和一个子类Dog。我想为每个创建 1 个实例并打印它们的count。这是工作代码:
class Animal:
count=0
def __init__(self):
Animal.count+=1
@classmethod
def getCount(cls):
return cls.count
class Dog (Animal):
count=0
def __init__(self):
super().__init__()
Dog.count+=1
a1=Animal()
print(Animal.getCount(),Dog.getCount())
d1=Dog()
print(Animal.getCount(),Dog.getCount())
它打印:
1 0
2 1
这是正确的,因为有 2 只动物,但其中只有 1 只是狗。
当我将计数变量创建为私有__count而不更改任何其他代码时,就会出现问题。
class Animal:
__count=0
def __init__(self):
Animal.__count+=1
@classmethod
def getCount(cls):
return cls.__count
class Dog (Animal):
__count=0
def __init__(self):
super().__init__()
Dog.__count+=1
a1=Animal()
print(Animal.getCount(),Dog.getCount())
d1=Dog()
print(Animal.getCount(),Dog.getCount())
现在,它打印:
1 1
2 2
似乎Dog类只访问Animal 的 __count。
你能检测出代码中的错误吗?
解决方案
简短的回答
当一个属性是私有的,例如__count
,这意味着它只能从同一个类中访问。Animal.__count
只能在 内访问Animal
,并且Dog.__count
只能在 内访问Dog
。
因为getCount
在 中定义Animal
,它只能访问Animal.__count
,所以这就是它返回的内容。
如果要访问子类的“私有”变量,请使用单个下划线前缀,例如_count
.
相关阅读:
详细介绍
私有变量是通过一种名为name mangling的机制来实现的。从文档:
由于类私有成员有一个有效的用例(即避免名称与子类定义的名称发生名称冲突),因此对这种机制的支持有限,称为name mangling。形式的任何标识符
__spam
(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_classname__spam
,其中classname
是当前类名,前导下划线被剥离。只要它出现在类的定义中,就无需考虑标识符的句法位置,就可以完成这种修饰。
这意味着您的代码被翻译成这样:
class Animal:
_Animal__count = 0
def __init__(self):
Animal._Animal__count += 1
@classmethod
def getCount(cls):
return cls._Animal__count
class Dog(Animal):
_Dog__count = 0
def __init__(self):
super().__init__()
Dog._Dog__count += 1
如果你这样看,很明显getCount
无法访问Dog
's__count
变量。
推荐阅读
- angular - 如果内容用 ngif 包裹,则 viewchild nativeElement 未定义
- python - Pygame 程序停止/崩溃而没有记录任何错误
- swift - 在 swift 中在 tableview 单元格内显示具有动态高度的 collectionview
- ios - 适用于 iOS 15 的 App Store 中的应用内事件页面的媒体规格是什么
- python - 如何在数据集中查找故障?
- python - django 的 Web 应用程序中的缓存有用吗?
- javascript - 退格时省略输入自定义美国电话掩码
- php - 查询执行被中断(超过 max_statement_time)
- typescript - 打字稿在类型映射表达式中的联合中查找
- r - R,合并两个数据集,分成多列