先说结论:
1、类属性属于类所有,建议引用时使用类名引用,形如 cls.attr。当然也可以使用实例引用 self.attr。
通过类名修改类属性后,若各实例未自行修改类属性,则引用到的值都会改变;
如果即通过实例修改类属性,会复制一份为实例属性,并覆盖类属性;
通过实例引用类属性会比较慢。
2、实例变量属于实例所有,引用方式形如self.attr。
class TestClass:
project_id: str = "类变量"
def __init__(self):
self.count = 1
# 类变量 当使用实例变量进行类变量赋值之后,就在实例中重新生成了一份变量
if __name__ == "__main__":
test_obj1 = TestClass()
test_obj2 = TestClass()
# 实例变量
print("实例变量:")
print(f"修改前,test_obj1实例变量count内存地址: {id(test_obj1.count)},值:{test_obj1.count}")
print(f"修改前,test_obj2实例变量count内存地址: {id(test_obj2.count)},值:{test_obj2.count}")
# 类名引用实例变量会报错
# print(f"修改前,类名引用实例变量count内存地址: {id(TestClass.count)},值:{TestClass.count}")
test_obj2.count = 2
test_obj1.count += 3
print(f"修改后,test_obj1实例变量count内存地址: {id(test_obj1.count)},值:{test_obj1.count}")
print(f"修改后,test_obj2实例变量count内存地址: {id(test_obj2.count)},值:{test_obj2.count}")
# 类变量
print("")
print("类变量:")
print(f"修改前,test_obj1类变量project_id内存地址: {id(test_obj1.project_id)},值:{test_obj1.project_id}")
print(f"修改前,test_obj2类变量project_id内存地址: {id(test_obj2.project_id)},值:{test_obj2.project_id}")
print(f"修改前,类变量project_id内存地址: {id(TestClass.project_id)},值:{TestClass.project_id}")
# 通过类修改类变量
print("通过类修改类变量")
TestClass.project_id = "第一次通过类修改类变量"
print(f"修改后:test_obj1类变量project_id内存地址: {id(test_obj1.project_id)},值:{test_obj1.project_id}")
print(f"修改后:test_obj2类变量project_id内存地址: {id(test_obj2.project_id)},值:{test_obj2.project_id}")
print(f"修改后:类变量project_id内存地址: {id(TestClass.project_id)},值:{TestClass.project_id}")
# 通过实例修改类变量
print("")
print("通过实例修改类变量")
test_obj1.project_id = "实例1类变量"
test_obj2.project_id = "实例2类变量"
print(f"修改后:test_obj1类变量project_id内存地址: {id(test_obj1.project_id)},值:{test_obj1.project_id}")
print(f"修改后:test_obj2类变量project_id内存地址: {id(test_obj2.project_id)},值:{test_obj2.project_id}")
print(f"修改后:类变量project_id内存地址: {id(TestClass.project_id)},值:{TestClass.project_id}")
# 再次通过类修改类变量,此时不会影响实例中的类变量了
print("再次通过类修改类变量,此时不会影响实例中的类变量了")
TestClass.project_id = "第二次通过类修改类变量"
print(f"修改后:test_obj1类变量project_id内存地址: {id(test_obj1.project_id)},值:{test_obj1.project_id}")
print(f"修改后:test_obj2类变量project_id内存地址: {id(test_obj2.project_id)},值:{test_obj2.project_id}")
print(f"修改后:类变量project_id内存地址: {id(TestClass.project_id)},值:{TestClass.project_id}")
实例变量:
修改前,test_obj1实例变量count内存地址: 2056885266736,值:1
修改前,test_obj2实例变量count内存地址: 2056885266736,值:1
修改后,test_obj1实例变量count内存地址: 2056885266832,值:4
修改后,test_obj2实例变量count内存地址: 2056885266768,值:2
类变量:
修改前,test_obj1类变量project_id内存地址: 2056893530448,值:类变量
修改前,test_obj2类变量project_id内存地址: 2056893530448,值:类变量
修改前,类变量project_id内存地址: 2056893530448,值:类变量
通过类修改类变量
修改后:test_obj1类变量project_id内存地址: 2056893605232,值:第一次通过类修改类变量
修改后:test_obj2类变量project_id内存地址: 2056893605232,值:第一次通过类修改类变量
修改后:类变量project_id内存地址: 2056893605232,值:第一次通过类修改类变量
修改实例引用的类变量,全部实例和类引用的类变量均会改变
修改后:test_obj1类变量project_id内存地址: 2056890801040,值:实例1类变量
修改后:test_obj2类变量project_id内存地址: 2056890800368,值:实例2类变量
修改后:类变量project_id内存地址: 2056893605232,值:第一次通过类修改类变量
再次修改类变量,此时不会影响实例引用的类变量了
修改后:test_obj1类变量project_id内存地址: 2056890801040,值:实例1类变量
修改后:test_obj2类变量project_id内存地址: 2056890800368,值:实例2类变量
修改后:类变量project_id内存地址: 2056893605328,值:第二次通过类修改类变量