Python类与self困惑:实例变量与类变量场景咨询
嘿,我完全懂你这种困惑!刚摸Python面向对象的时候,self关键字和类/实例变量的区别真的容易绕得人头晕,尤其是碰到这种共享变量的坑的时候。咱们就拿你提到的这个Dog类例子来掰扯清楚,保证你能搞明白~
先搞懂
self到底是啥 简单说,self就是当前实例对象本身。当你创建一个Dog实例,比如my_dog = Dog("旺财"),调用方法的时候Python会自动把my_dog这个实例作为第一个参数传给self。所以你在方法里写self.xxx,就是在操作这个实例自己的专属属性,而不是整个类的公共属性。
你的
Dog类踩了啥坑? 先把你给出的代码补全(应该是没写完),常见的错误写法大概是这样:
class Dog: tricks = [] # 这是类变量,属于整个Dog类,所有实例共享 def __init__(self, name): self.name = name # 这是实例变量,每个Dog实例自己独有 def add_trick(self, trick): self.tricks.append(trick) # 这里看似操作实例属性,实则踩了坑!
咱们跑一下测试代码看看问题:
dog1 = Dog("旺财") dog2 = Dog("来福") dog1.add_trick("握手") dog2.add_trick("打滚") print(dog1.tricks) # 输出['握手', '打滚']——旺财没学打滚啊! print(dog2.tricks) # 同样输出['握手', '打滚']
为啥会这样?因为tricks是类变量,当你用self.tricks.append()的时候,dog1实例自己并没有tricks属性,Python就会去类里找这个公共变量,然后修改的是整个Dog类的tricks列表,所有实例自然就共享这个列表了,结果所有狗的技能都混在一起了。
正确写法:让每个狗有自己的技能列表
要让每个狗拥有独立的技能,就得把tricks变成实例变量,在__init__方法里给每个实例单独初始化一个空列表:
class Dog: def __init__(self, name): self.name = name self.tricks = [] # 每个实例创建时,都生成自己的专属空列表 def add_trick(self, trick): self.tricks.append(trick) # 现在操作的是当前实例自己的tricks!
再跑测试看看:
dog1 = Dog("旺财") dog2 = Dog("来福") dog1.add_trick("握手") dog2.add_trick("打滚") print(dog1.tricks) # 输出['握手']——正确,这是旺财的技能 print(dog2.tricks) # 输出['打滚']——正确,这是来福的技能
那类变量什么时候用?
类变量适合所有实例共享的属性,比如所有狗都有四条腿,那可以设个类变量:
class Dog: legs = 4 # 类变量,所有Dog实例共享 def __init__(self, name): self.name = name self.tricks = []
这样不管创建多少狗实例,legs都是4;如果修改类变量,所有没单独设置legs的实例都会跟着变:
Dog.legs = 3 # 修改类变量 print(dog1.legs) # 输出3 print(dog2.legs) # 输出3 dog1.legs = 5 # 给dog1单独设置legs,此时dog1的legs变成实例变量,不再和类变量关联 print(dog1.legs) # 输出5 print(dog2.legs) # 还是3
最后划个重点
self:代表当前实例,用self.xxx优先访问实例的专属属性,实例没有的话才会去类里找类变量。- 类变量:定义在类里、
__init__外面,所有实例共享,修改会影响所有未单独设置该属性的实例。 - 实例变量:定义在
__init__里(或其他方法中用self.xxx赋值),每个实例独有,互不干扰。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

