我们接着讲解Python的面向对象
1.初始化实例属性
在现实生活中,一种类型的实例会具有相同的某些属性,把这些实例划分为一个类型,则这些实例必然有相似的部分。但是,在创建实例之后,我们一个一个的为实例赋予 属 性,这样就显得非常耗时。
如果我们在定义类的时候,就让他拥有某些共有的属性,那这样就显得轻松多了。
在定义Person类的时候,可以为类添加一个特殊的__init__()方法,当创建实例时,__init__()方法会被自动调用,这样我们就可以为每个实例都统一加上共有的属性。
注意:__init__()方法的第一个参数必须是self,后续的参数则可以自由指定,当然,在创建实例的时候,就必须要提供除self以外的参数。
这样,有了__init__()方法,每个实例在创建的时候,都会具有这些共有的属性。
实例访问属性的时候,使用‘.’操作符。即“对象.属性”,xiaoming.name。
如果忘记了写self参数,程序就会出现以下错误:
接下来我们谈谈访问控制
2.访问控制
一个实例对象可以绑定很多属性,但是有些属性我们并不像让外面的世界知道,这时我们就要对这些属性进行访问权限的控制,那么Python是怎么进行访问控制的 呢!!!
Python对属性的权限控制是通过属性名来实现的,如果一个属性由双下划线(__)开头,则该属性就无法被外部访问。
从上面代码,可知,只有以双下划线开头的“__work”,不能直接被外部访问。
但是,如果一个属性以“__xxx__”形式定义,那它又可以被外部访问了。
“__xxx__”形式在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不把普通属性用“__xxx__”定义。
如果把实例化时传入的参数赋值给一个“__xxx”的属性,看是否能从外部访问?
从上面代码的执行结果可以看出,并不能被外部访问。
3.创建类属性
类是模板,而实例则是根据类创建的对象。
绑定在实例上的属性不会影响其他实例,但是,类本身也可以看做是一个对象,那么,如果在类上绑定一个属性,则所有的实例都可以访问类的属性,并且,所有的实例访 问的类属性都是同一个,换言之,实例属性每个实例各自拥有,相互独立,而类属性有且只有一份。
定义类属性:
从上面的代码可以看出,类属性可以直接在class中定义(address = ‘Earth’),所以访问类属性时,不需要创建实例,直接通过类名就可以访问 Person.address
当然,对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性。
注意:
由于Python是动态语言,类属性也是可以动态添加和修改的
因为类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了!
4.类属性和实例属性名字冲突问题
修改类属性会导致所有实例访问到的类属性全部都受影响,如果在实例变量上修改类属性会发生什么呢!!!
从上面代码,我们可以看出,实例变量上修改类属性,并不影响其他实例和类的类属性,只有该实例进行了变化,这是怎么回事呢!!
其实是p1.address = ‘China’ 并没有改变Person的address,而是给p1这个实例绑定了实例属性address,值为’China’,而它所属的类也有一个类属性address,所以访 问p1.address时,优先查找实例属性,返回‘China’,访问p2.address时,p2没有实例属性address,但是有类属性address,因此返回’Earth’。
当我们把p1的address实例属性删除后,访问p1.address就又返回类属性的值‘Earth’了。
总结:
@1.当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
@2.不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。