1. 对象名调用类属性,当类属性是个可变数据类型:
之前讲过,当对象名调用类属性时,类属性是个不可变数据类型(上一节中是字符串),然后通过对象名调用类属性修改类属性,是不会影响类命名空间中的类属性值
但是当类属性是个可变数据类型,再使用对象名调用类属性,修改类属性的话就会变化:
class Course(): language=['Chinese'] # 这里的类属性是个可变数据类型! def __init__(self,name,period): self.name=name self.period=period def func(self): pass c1=Course('python','3 mon') c2=Course('Linux','2 weeks') print('对象名调用类属性,修改类属性之前:') print(Course.__dict__) print(c1.__dict__) print(c2.__dict__) c1.language[0]='中文' # 这样才是修改 print("对象名调用类属性,修改类属性之后:") print(Course.__dict__) print(c1.__dict__) # 发现c1对象命名空间中并没有language这个属性,就是因为c1.language[0]='新值'修改的是类命名空间中的类属性,不会在对象c1命名空间中创建 print(c2.__dict__)
运行结果:
过程是这样的:关于列表修改值:
但是一定要注意:如果是下面这种方式通过修改对象名调用类属性的方式是完全不一样的!
class Course(): language=['Chinese'] # 这里的类属性是个可变数据类型! def __init__(self,name,period): self.name=name self.period=period def func(self): pass c1=Course('python','3 mon') c2=Course('Linux','2 weeks') print('对象名调用类属性,修改类属性之前:') print(Course.language) print(Course.__dict__) print(c1.__dict__) print(c2.__dict__) c1.language=['中文'] # 这样通过赋值,是不会改变类命名空间中的类属性,只会在c1对象的命名空间创建一个language属性 print("对象名调用类属性,修改类属性之后:") print(Course.language) print(Course.__dict__) print(c1.__dict__) # 发现c1对象命名空间中并没有language这个属性,就是因为c1.language[0]='新值'修改的是类命名空间中的类属性,不会在对象c1命名空间中创建 print(c2.__dict__)
运行结果:(不同在c1.language=['中文']这里是通过赋值,不是改变原来的)
2. 模拟人生
之前讲过类名调用类属性时,修改类属性的值,对象再调用类属性值时会发生改变;
但是当对象名调用类属性时,如果是不可变数据类型,对象名调用类属性,通过赋值企图修改类属性不会影响类命名空间中的类属性;
如果我们像设计一款游戏:
class Person(): money=0 # 类属性 mom=Person() father=Person() mom.money+=1000 father.money+=1000 print(Person.money)
运行结果:
会发现实例化两个对象,分别对象名调用类属性money并不会改变类中类属性值,这就是之前说的,对象名调用类属性,会查看然后企图通过赋值 是不会修改类中类属性的值,只会在对象命名空间中创建一个新的属性,就是因为它是+=是赋值,并没有修改,它也改不了(除非是类属性是可变数据类型,而且想通过对象名调用类属性修改类中类属性的值,也只能Course.language[0]='中文'这种方式,就是一定要分清赋值和修改操作!!,赋值就是没有就建一个新的,原来的并不改变)
所以我们要想通过mon,father赚的钱都同步到类属性money上,必须通过这种方式:
class Person(): money=0 # 定义一个类属性 def work(self): Person.money+=1000 mom=Person() father=Person() mom.work() father.work() print(Person.money) print(mom.money)
运行结果:
就是改变的必须是类命名空间中的类属性,企图通过对象名调用类属性,通过赋值语句并不会改变类命名空间中的类属性,只会在对象的命名空间中新建一个属性而已;
3.实现一个功能,每实例化一个对象就要记录下来次数:
其实本质还是改变的类属性的值:
class Counter(): n=0 # 定义一个类属性 def __init__(self): Counter.n+=1 # 因为对类实例化为对象时就会自动执行初始化方法,然后在这里通过类名调用类属性改变类属性的值 c1=Counter() c2=Counter() c3=Counter() c4=Counter() print(Counter.n) print(c1.n) # 所有的对象调用类属性时都会知道这个类被调用了多少次了,因为是改变的类命名空间中的类属性,所以对象调用类属性也会捕捉到值会改变
运行结果: