12、Python之面向对象基础篇
一、什么是面向对象编程
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
面向对象的几个核心特性如下
Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
二、Python中实现面向对象的基本语法
1、定义一个类
在python中定义一个类使用关键字class,基本语法如下:
1 class Student(object): 2 def __init__(self,id,name,age): #构造函数 3 self.id = id 4 self.name = name 5 self.age = age 6 def Introduce_youself(self): 7 print("大家好,我的学号是%s,我叫%s,今年%s" % (self.id,self.name,self.age)) 8 def __del__(self): #析构函数 9 print("析构函数,对象被销毁前执行")
上面的代码定义了一个学生类,该类有三个属性id,name和age。有三个方法,__init__,Introuce_yourselft,__del__。其中__init__为构造方法,在创建对象的时候调用,__del__为析构方法在销毁对象的时候由系统自动调用。
基于定义好的学生类,我们创建一个对象并使用这个对象调用其Introuce_yourselft方法,代码如下:
1 stu = Student(1,"高文祥",18) #创建一个名字为stu的对象 2 stu.Introduce_youself() 3 #执行结果为大家好,我的学号是1,我叫高文祥,今年18 4 #析构函数,对象被销毁前执行
第1行代码,创建一个stu对象(语法虽然为Student(....),但实际是调用__init__(......)方法),第2行代码使用stu对象调用Introuce_yourselft方法,我们发现执行结果最后打印了第4行的信息,正如我们之前所说的,析构函数是对象被销毁之前由系统调用的。
2、类属性和对象属性
上面创建的stu对象有三个属性(id,name,age),如果想要给stu对象再增加一个性别属性,直接使用 stu.sex = '男' 即可。如果这时候再创建一个对象stu2,stu2中是没有sex属性的。那到底什么是类属性和对象属性呢?不要方,我们来看一个列子,定义如下的学生类,并创建两个对象stu_01和stu_02。
1 class Student(object): 2 count = 0 #班级人数 3 def __init__(self,id,name,age): #构造函数 4 self._id = id 5 self._name = name 6 self._age = age 7 8 stu_01 = Student(1,"张三",18) 9 stu_02 = Student(2,"李四",20) 10 print("Student的count值为:%s,stu_01的count值为:%s,stu_02的count值为:%s" % (Student.count,stu_01.count,stu_02.count)) 11 print("Student的count值为:%s,stu_01的count值为:%s,stu_02的count值为:%s" % (Student.count,stu_01.count,stu_02.count)) 12 stu_02.count = stu_02.count + 1 13 print("Student的count值为:%s,stu_01的count值为:%s,stu_02的count值为:%s" % (Student.count,stu_01.count,stu_02.count)) 14 Student.count = Student.count + 1 15 print("Student的count值为:%s,stu_01的count值为:%s,stu_02的count值为:%s" % (Student.count,stu_01.count,stu_02.count))
执行结果:
Student的count值为:0,stu_01的count值为:0,stu_02的count值为:0
Student的count值为:0,stu_01的count值为:1,stu_02的count值为:0
Student的count值为:0,stu_01的count值为:1,stu_02的count值为:1
Student的count值为:1,stu_01的count值为:1,stu_02的count值为:1
上面我们涉及的列子中,对象的属性都是可以通过对象直接操作的,但有的时候,我们不会让对象直接操作数据,而是提供一些方法供其调用(get,set方法),如果想要实现这样的效果,需要将属性设置为私有属性。
例如将上述年龄属性定义为私有属性的语法为:self.__age = age。加__即可,这时候再使用对象直接访问age属性的时,解释器就会报错了。
3、继承
所谓继承即子类继承父类的,便继承了父类的所有属性和方法。例如有一个Animal和Dog类,Dog类继承Animal类。
1 class Animal(object):#动物类 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 def sleep(self): 6 print("Animal is sleeping",self.name,self.age) 7 class Dog(Animal,object): 8 def __init__(self,name,age,size): 9 #Animal.__init__(self,name,age) 10 super(Dog,self).__init__(name,age) 11 self.size = size 12 def print_self(self): 13 print(self.name,self.age,self.size) 14 15 dog = Dog("狗1",19,20) 16 dog.sleep() 17 dog.print_self()
Dog类拥有了Animal类的所有属性和方法。
现在我们来看一下多继承中构造函数的执行顺序,假设有A、B、C,D三个类的定义,及其之间的关系如下:
那么当创建D的对象时,构造方法的执行顺序是神马样子的呢?
1 class A(object): 2 def __init__(self): 3 print("A的构造函数") 4 5 class B(A,object): 6 # def __init__(self): 7 # print("B的构造函数") 8 pass 9 10 11 class C(A,object): 12 # def __init__(self): 13 # print("C的构造函数") 14 pass 15 class D(B,C,object): 16 # def __init__(self): 17 # print("D的构造函数") 18 pass 19 d = D()
当创建D的对象时,先搜索D的构造方法,查到即停止,如果D没有构造方法,则查到B的构造方法,如果B没有构造方法则查找C,最后是A。也就是搜索的顺序为:D->B->C->A。
4、多态
多态的意义在于,向外界暴露一个固定的标准接口,对于不同的对象的行为将会进行不同的响应,具体代码实现如下:
1 class Animal(object): 2 @staticmethod 3 def talk(obj): 4 obj.talk() 5 class Dog(Animal): 6 def talk(self): 7 print("dog is talking") 8 class Cat(Animal): 9 def talk(self): 10 print("Cat is talking") 11 dog = Dog() 12 cat = Cat() 13 Animal.talk(cat) 14 Animal.talk(dog)
新春第一课,祝各位开工大吉,薪资翻倍!