学过JAVA或C++等语言的程序员再去学Python类设计时感觉非常不适应,因为Python是在太自由了,让人无所适从,来python定义类时的变量来说,其定义方式、作用域、操作方法都与上述两种语言有更大的可操作空间。
Python类中定义的变量分为类变量和实例变量(也叫成员变量、对象变量),类变量直接定义在类里面(不在函数里面),前面不会有一个self修饰;相反,实例变量大都定义在实例函数里面,通过“self.变量名”的方式进行定义。当然,也有例外,应该类变量和实例变量都可以在类定义之后在定义(这个功能让我目瞪口呆)。
一、类变量及实例变量的定义
先看看正常的:
class Person(): person = 'alive' #这是类变量 def __init__(self,name ,age): self.name = name #这是实例变量 self.age = age #这是实例变量 self.gender = '男' #这是实例变量 #a = 456 #不能写这里,会出错 place = ['地球','中国'] #这是类变量
从上述代码也可以看出,Python定义类时,不对定义类变量与实例变量之间的顺序做出约束,也可以看出类变量不能定义在函数体里面。
再来看看返厂的,也就是在类定义之后在定义变量:
class Student():#创建一个空的类 pass #Student s1 = Student() #为p1添加一个name属性 s1.name = 'chb' #这个name属性是一个实例变量 print(s1.name) #输出结果:chb #为Person类添加一个类变量 Student.behavior = 'study' #这是一个类变量 print(Student.behavior)#输出结果:study print(s1.behavior)#输出结果:study
所以说,Python类的定义是很自由的,对于变量,既可以在定义类时定义,也可以在类定义完成之后定义。上述两块代码讲述了类变量和实例变量在定义上面的区别。下面说说类变量与实例变量在使用上的区别。
二、类变量与实力变量的使用
结合上述第一个代码块中定义的Person类进行说明。
1. 类变量可以通过“类名.类变量名”、“实例名.类变量名”两种方式读取,即类和实例都能读取类变量。
if __name__=="__main__": p = Person('chb' , 18) print(Person.person)#输出结果:alive print(p.person) #输出结果:alive
2实例变量只能通过“实例名.实例变量名”的方式访问,类无权访问实例名。
if __name__=="__main__": p = Person('chb' , 18) print(p.name)#输出结果:chb print(Person.name) #错误:AttributeError: type object 'Person' has no attribute 'name'
3. “类名.类变量名”、“实例名.类变量名”访问的实际上是同一个命名空间的变量,所以类变量具有“一改全改”的特点。
if __name__=="__main__": p = Person('chb' , 18) Person.person = 'die' print(p.person)#输出结果:die print(Person.person) #输出结果:die
4. 采用‘实例名.类变量名’的方式对类变量进行赋值时,若该类变量是可变数据类型,则可以成功赋值该类变量,否则会在该实例变量所在的名称空间中创建一个与该类变量同名的实例变量进行赋值,并不会对类变量进行赋值,此时也无法再通过‘实例名.类变量名’的方式读取该类变量。但若‘实例名.类变量名’赋值的是可变数据类型,则可以对类变量进行赋值操作。
if __name__=="__main__": p = Person('chb' , 18) p.person = 'die' print(p.person)#输出结果:die print(p.__dict__)#输出结果:{'gender': '男', 'person': 'die', 'age': 18, 'name': 'chb'} print(Person.person) #输出结果:alive p.place[1] = '北京' print(p.place)#输出结果:['北京' , '北京'] print(Person.place)#输出结果:['北京' , '北京']