实例变量与类变量不得不说的二三事
1. 类变量作用及解析
类变量:实例共用的属性。
比方说country 这个属性如果设置为实例属性,创建5个对象的时候,country 就需要初始化5次,但这个属性对于各个实例是相同的,每次都需要创建会造成资源浪费。类变量只会在创建类的时候生成一次,对于不同对象来说无区别的对象我们可以设置为类变量。
class Chinese: country = 'China' def __init__(self, name, age,country): self.name = name self.age = age self.country = country
2. 类变量、实例变量查找优先级
优先查找实例变量,找不到再去查找类变量。就是说类变量和实例变量名相同的情况下,返回的是实例变量的值,代码如下:
class Chinese: country = 'China' age = 72 def __init__(self, name, age): self.name = name self.age = age def talk(self): print(self, 'is talking Chinese') if __name__ == '__main__': DY = Chinese("DY", "18") print(DY.age) 执行结果: 18 # 18为实例DY的属性值
3. 实例增删改查类的变量、方法
实例是可以直接操作类的变量或方法的,可进行查询、更改、新增、删除的,如果是使用这些方法时,仅推荐操作实例属性,其他属性因为存储在类的命名空间内,操作的话会影响其他实例,Python真的是很不严谨;但其实实例的属性、方法也是不推荐操作如更改、删除的,这就引入了私有变量或方法。
class Chinese: country = 'China' def __init__(self, name, age): self.name = name self.age = age def talk(self): print(self, 'is talking Chinese') @staticmethod def nationality(): print("国籍归属于{}".format(Chinese.country)) if __name__ == '__main__': DY = Chinese("DY", 18) print(DY.age) # 查询实例变量值 DY.age = 19 # 更改实例变量的值,思考更改类变量的值? print(DY.age) DY.sex = "女" # 对象新增实例变量 print(DY.sex)
4. 实例可以更改类变量值吗?
实例对类变量赋值(更改类变量)为什么未改变类变量值?对象给类变量赋值实际是给实例增加一种新的属性,是在对象内存空间中新增了一个变量,而使用变量的时候又是优先查找实例变量,所以打印对象的类变量时,实际是查的对象的实例属性,从根本上并未影响到类变量,也就不会影响到其他对象的类变量值。
简而言之,你觉得是在更改类变量的值,实际是给实例新增了一个实例属性。
class Chinese: country = 'China' def __init__(self, name, age): self.name = name self.age = age def talk(self): print(self, 'is talking Chinese') if __name__ == '__main__': DY1 = Chinese("DY", "18") DY2 = Chinese("DY", "19") DY1.country = "zhongguo" print(DY1.country) print(DY2.country) 执行结果: zhongguo # 实际相当于给实例DY1新增了个实例属性 China # 实例DY2并不受影响
5. 类属性慎用可变数据结构
class Chinese: country = 'China' populations = [] def __init__(self, name, age): self.name = name self.age = age def talk(self): print(self, 'is talking Chinese') @staticmethod def nationality(): print("国籍归属于{}".format(Chinese.country)) def add_people(self): Chinese.populations.append(self.name) if __name__ == '__main__': DY1 = Chinese("DY", 18) DY2 = Chinese("DY1", 18) DY1.add_people() print(DY1.populations) DY2.add_people() print(DY2.populations) 执行结果: ['DY'] ['DY', 'DY1']
由执行结果可以看出,两个实例同时操作类变量时是会相互影响的, 对象DY1操作populations属性也会影响到DY2的populations ,如果是在程序中是会出bug的,而且问题不好查找,就好比说对象A与对象B同时在做任务,并且共享任务列表,对象A完成后发通知说任务已完成,导致对象B实际未做完也发通知报告已完成。
划重点:可变数据结果一般不能用作类变量的值。如果变量的值为可变数据,需要写在__init__里面,写成self. populations = [],这样在初始化对象的时候,每个对象的populations的值都会初始化为一个空列表,对象间属性独立。
每天进步一小步 日积月累跨大步