Python类级属性值的求值机制及实例属性意外同步问题咨询
问题解答:Python类级属性求值与实例共享问题
嘿,我来帮你拆解这两个问题~
一、Python中类级属性的求值逻辑
- 类级属性是定义在类内部、方法之外的属性,它属于类本身,而非类的某个具体实例。
- 当你创建类的实例后,如果实例自己没有定义同名属性,访问该属性时会直接引用类级属性的取值。
- 只有当你给实例的同名属性赋值时,才会在实例自身的命名空间中创建这个属性,后续访问就会优先使用实例自己的属性,不会再影响类级属性。
二、你的代码异常原因分析
先来看你的代码片段:
class StarCount: one_stars = 0 two_stars = 0 three_stars = 0 four_stars = 0 five_stars = 0 class OrientationAnalysis: straight = StarCount() bisexual = StarCount() gay = StarCount() class GenderAnalysis: men = OrientationAnalysis() women = OrientationAnalysis() genderanalysis = GenderAnalysis() genderanalysis.men.straight.five_stars = 100 print(genderanalysis.men.straight.five_stars) # 输出100 print(genderanalysis.women.straight.five_stars) # 同样输出100
问题的核心出在OrientationAnalysis的类级属性设计上:
OrientationAnalysis里的straight、bisexual、gay是在类定义阶段就创建好的StarCount实例,它们隶属于OrientationAnalysis这个类,而不是某个OrientationAnalysis实例。- 当你创建
GenderAnalysis的实例genderanalysis后,genderanalysis.men和genderanalysis.women都是OrientationAnalysis的实例,但它们俩访问straight时,用的都是同一个类级的StarCount实例(因为这两个OrientationAnalysis实例自己都没有定义straight属性)。 - 所以你修改
genderanalysis.men.straight.five_stars,本质是修改了那个被共享的StarCount实例的属性值,genderanalysis.women.straight指向的是同一个实例,自然也会显示更新后的100。 - 至于
genderanalysis.women.gay.five_stars没变化,是因为你从来没有对这个共享的gay对应的StarCount实例做过赋值操作,它的five_stars还是初始的0。
解决方法
如果想要每个OrientationAnalysis实例都拥有独立的StarCount实例,互不干扰,你需要把这些属性放到类的__init__方法中,让每个实例初始化时都创建自己的StarCount对象:
class OrientationAnalysis: def __init__(self): self.straight = StarCount() self.bisexual = StarCount() self.gay = StarCount()
这样修改后,genderanalysis.men和genderanalysis.women就会拥有各自独立的straight、bisexual、gay实例,修改其中一个不会影响另一个。
内容的提问来源于stack exchange,提问作者Nayan
相关产品推荐
相关产品推荐

