最近使用Python开发项目时遇到了一些类变量的问题,所以抽空做了一下验证,在此做个记录和分享,如理解有误,请批评指正,谢谢。
写作思路:本文会先给出自己得出的结论,然后对逐个对结论进行验证,这样方便大家理解。
图解部分是为了大家理解方便,自己通过打印变量的地址得出,有根据,但实际是否和我猜想一致,需后续再深入探究。
结论:
- 子类会继承父类的所有类变量
- 子类若没有重新定义父类的类变量,则默认使用父类的类变量,且随父类类变量的变化而变化。
- 子类若重新定义了部分父类的类变量,则重新定义的部分不会随着父类类变量的变化而变化。
- 子类对类变量重新赋值后,重新赋值的类变量不再受父类类变量的变化而变化。
- 子类修改类变量的值对父类没有影响
结论1
子类会继承父类的所有类变量
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
pass
if __name__ == '__main__':
print("儿子的 name : {} 儿子的角色 :{}".format(Son.name,Son.role))
pass
输出:
儿子的 name : 老爸 儿子的角色 :老爸是家里的顶梁柱
图解:
从上边例子中可以看出,子类虽然没有定义 name 和 role ,但是可以获取到并且显示的是父类的name 和 role。
结论2
子类若没有重新定义父类的类变量,则默认使用父类的类变量,且随父类类变量的变化而变化。
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
pass
if __name__ == '__main__':
print("儿子的 name : {} 儿子的角色 :{}".format(Son.name,Son.role))
father = Father()
son1 = Son()
print("father name : {} father 的角色 :{}".format(father.name, father.role))
print("son1 name : {} son1 的角色 :{}".format(son1.name, son1.role))
Father.name = "亲爱的老爸"
print("----------------------add for 结论2-------------------")
print("father name : {} father 的角色 :{}".format(father.name, father.role))
print("son1 name : {} son1 的角色 :{}".format(son1.name, son1.role))
print("----------------------add for 结论2-------------------")
pass
输出:
儿子的 name : 老爸 儿子的角色 :老爸是家里的顶梁柱
father name : 老爸 father 的角色 :老爸是家里的顶梁柱
son1 name : 老爸 son1 的角色 :老爸是家里的顶梁柱
------------------------------add for 结论2------------------------------
father name : 亲爱的老爸 father 的角色 :老爸是家里的顶梁柱
son1 name : 亲爱的老爸 son1 的角色 :老爸是家里的顶梁柱
------------------------------add for 结论2------------------------------
图解:
在这个例子中,子类中我们没有重新定义父类的类变量,我们可以发现我们修改了父类的类变量name的值,子类的name值也发生了变化。
结论3
子类若重新定义了部分父类的类变量,则重新定义的部分不会随着父类类变量的变化而变化。
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
# add for 结论 3
name = "儿子"
# add for 结论 3
pass
if __name__ == '__main__':
print("儿子的 name : {} 儿子的角色 :{}".format(Son.name,Son.role))
father = Father()
son1 = Son()
print("father name : {} father 的角色 :{}".format(father.name, father.role))
print("son1 name : {} son1 的角色 :{}".format(son1.name, son1.role))
print("------------- add for 结论 3 ------------")
Father.name = "亲爱的老爸"
Father.role = "父亲也是最严厉的那个人"
print("------------- add for 结论 3 ------------")
print("father name : {} father 的角色 :{}".format(father.name, father.role))
print("son1 name : {} son1 的角色 :{}".format(son1.name, son1.role))
pass
输出:
儿子的 name : 儿子 儿子的角色 :老爸是家里的顶梁柱
father name : 老爸 father 的角色 :老爸是家里的顶梁柱
son1 name : 儿子 son1 的角色 :老爸是家里的顶梁柱
------------- add for 结论 3 ------------
------------- add for 结论 3 ------------
father name : 亲爱的老爸 father 的角色 :父亲也是最严厉的那个人
son1 name : 儿子 son1 的角色 :父亲也是最严厉的那个人
图解:
在这个例子中,子类重新定义了 name 字段,父类修改了name 和 role 字段后,子类的name字段并没有随之修改,而未重新定义的role字段与父类role保持一致。
结论4
子类对类变量重新赋值后,重新赋值的类变量不再因父类类变量的变化而变化。
结论 3 中的例子已经可以说明该问题,在此单独列出来是因为修改子类类变量的方法有多种,觉得有必要写一下。
第一种:在书写子类的时候进行定义并赋值
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
# 第一种
name = "儿子"
# 第一种
第二种:使用子类类名进行重新赋值
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
pass
if __name__ == '__main__':
# 第二种
Son.name = "儿子"
Son.role = "儿子是未来的希望"
# 第二种
第三种:使用类方法进行修改
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
pass
#---------------------- 类方法写法 --------------------------
@classmethod
def reset_name(cls,name):
cls.name = name
@classmethod
def reset_role(cls,role):
cls.role = role
#---------------------- 类方法写法 --------------------------
if __name__ == '__main__':
# 第三种
Son.reset_name("儿子")
Son.reset_role("儿子是未来的希望")
# 第三种
结论5
子类修改类变量的值对父类没有影响
class Father():
name = "老爸"
role = "老爸是家里的顶梁柱"
class Son(Father):
pass
if __name__ == '__main__':
father = Father()
son1 = Son()
print("father name : {} father 的角色 :{}".format(father.name, father.role))
print("son1 name : {} son1 的角色 :{}".format(son1.name, son1.role))
Son.name = "儿子"
Son.role = "儿子是未来的希望"
print("father name : {} father 的角色 :{}".format(father.name, father.role))
print("son1 name : {} son1 的角色 :{}".format(son1.name, son1.role))
pass
输出:
father name : 老爸 father 的角色 :老爸是家里的顶梁柱
son1 name : 老爸 son1 的角色 :老爸是家里的顶梁柱
father name : 老爸 father 的角色 :老爸是家里的顶梁柱
son1 name : 儿子 son1 的角色 :儿子是未来的希望
图解:
从这个例子中可以看出,修改了儿子的类变量name 和 role 后,父类的 name 和 role 并没有发生变化。