面向对象编程
类
定义:是一个抽象的模板。
通过关键字class来定义。
class + 类名(object)
class Student(object)
类名首字母一般是大写。object表示该类从哪个类继承下来。
实例
定义:根据类创建出的一个个具体的对象。
实例 = 类名()
bart = Student()
bart指向Studen的实例。
可以给实例绑定属性。
bart.name = ‘Ann’
在创建实例的时候,可以把必须绑定的属性添加进去。通过定义一个特殊的init方法。
def __init__(self, name, score):
self.name = name
self.score = score
到_init_方法的第一个参数永远是self,表示创建的实例本身,因此,在_init_方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本
身。有了_init_方法,在创建实例的时候,就不能传入空的参数了,必须传入与_init_方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
bart = Student('Bart Simpson', 59)
>>>bart.name
'Bart Simpson'
>>>bart.score
59
属性相当于普通函数的参数,在类中定义的函数,第一个参数永远是实例变量self,调用时,不需要传递参数,只需要添加属性。
数据封装
直接在类的内部定义访问数据的函数,相当于把“数据”封装起来了,封装这些数据的函数与类本身是关联的,称之为类的方法。
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
init和print_score都是类的方法,而print_score是从内部访问数据。
>>> bart.print_score()
Bart Simpson: 59
要调用,直接在实例变量上调用。
实例变量 + .方法
访问限制
从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性:
>>> bart = Student('Bart Simpson', 59)
>>> bart.score
59
>>> bart.score = 99
>>> bart.score
99
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线,在Python中,实例的变量名如果以开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:
class Student(object):
...
def get_name(self):
return self.__name
def get_score(self):
return self.__score
如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:
def set_score(self, score):
self.__score = score
在Python中,变量名类似xxx的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用name、score这样的变量名。
练习
请把下面的Student对象的gender字段对外隐藏起来,用get_gender()和set_gender()代替,并检查参数有效性:
class Student(object):
def __init__(self, name, gender):
self.__name = name
self.__gender = gender
def get_gender(self):
return self.__gender
def set_gender(self, gender):
self.__gender = gender
bart = Student('Ann', 'male')
if bart.get_gender() != 'male':
print('测试失败')
else:
bart.set_gender('female')
if bart.get_gender() != 'female':
print('测试失败')
else:
print('测试成功')
测试结果:
测试成功
【注意】
在类的方法中,self.__name = name ,是指绑定属性。
在外部访问下,改变直接在实例后面改变参数, bart.name = ‘Ann’
在外部不可以访问下,利用set改变:
bart.set_gender(‘female’)
继承
已经定义一个class的时候,可以继承某个现有的class,新的class称为子类,被继承的class称为父类。
编写一个class,有一个run()方法:
class Animal(object):
def run(self):
print('Animal is running...')
当需要编写子类,Dog和Cat类时,直接从Animal类继承:
class Dog(Animal):
pass
class Cat(Animal):
pass
子类中的(object)就是Animal。
class Dog(Animal):
pass
class Cat(Animal):
pass
子类中的(object)就是Animal。
继承优点一:父类实现了什么功能,子类就继承了父类全部的功能。
dog = Dog()
dog.run()
cat = Cat()
cat.run()
结果:
Animal is running...
Animal is running...
优点二:可以对代码进行修改,添加一些方法。
class Dog(Animal):
def run(self):
print('Dog is running...')
class Cat(Animal):
def run(self):
print('Cat is running')
结果:
Dog is running...
Cat is running...
子类和父类存在相同的run()方法时,子类会覆盖父类的方法,执行子类下run()方法。
优点三:获得多态。
需要新编写一个函数:
def run_twice(animal):
animal.run()
传入Animal的实例时:
>>> run_twice(Animal())
Animal is running...
传入Dog的实例时:
>>> run_twice(Dog())
Dog is running...