Python基础篇【第十三篇】:面向对象
面向对象编程简称OOP(OOP,object-oriented programming)是一种程序设计思想,OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向对象设计简称OOD(OOD,object-oriented design)OOD仅意味着来创建你采用面向对象方式架构来创建系统.
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
面向对象常用的术语:
1.类(class):
用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
2.类变量:
类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
3.数据成员:
类变量或者实例变量用于处理类及其实例对象的相关的数据。
4.方法重写:
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
5.实例变量:
定义在方法中的变量,只作用于当前实例的类。
6.继承:
即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
7.实例化:
创建一个类的实例,类的具体对象。
8.方法:
类中定义的函数。
9.对象:
通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
类的综合表现形式:
class ClassName_1: #定义类 def __init__(self, nm, ph): #定义构造器 self.nm = nm #设置名字 self.ph = ph print('类self指向的内存地址:', self) print(self.nm) print(self.ph) def def_name_1(self, newph): #定义方法 self.nm = self.nm self.ph = newph #重新命名 print('方法self指向的内存地址:', self) print(self.nm) print('新的电话号码:',self.ph) class ClassName_2(ClassName_1): #创建子类 def __init__(self, nm, ph, id, em): super(ClassName_2, self).__init__(nm, ph) self.id = id self.em = em print('类self指向的内存地址:', self) # print(self.nm) # print(self.ph) print(self.id) print(self.em) def def_name_2(self, newemail): self.id = self.id self.em = newemail print('类self指向的内存地址:', self) # print(self.nm) # print(self.ph) print(self.id) print(self.em)
运算结果:
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/zk/PycharmProjects/old_boy/week06/class_面向对象.py 类self指向的内存地址: <__main__.ClassName_1 object at 0x101b84208> 小明 110 实例化ret_2指向的内存地址: <__main__.ClassName_1 object at 0x101b84208> 方法self指向的内存地址: <__main__.ClassName_1 object at 0x101b84208> 小明 新的电话号码: 110 类self指向的内存地址: <__main__.ClassName_2 object at 0x101b842e8> 小红 119 类self指向的内存地址: <__main__.ClassName_2 object at 0x101b842e8> 66 123@qq.com 实例化ret_2指向的内存地址: <__main__.ClassName_2 object at 0x101b842e8> 类self指向的内存地址: <__main__.ClassName_2 object at 0x101b842e8> 66 qwe@163.com 方法self指向的内存地址: <__main__.ClassName_2 object at 0x101b842e8> 小红 新的电话号码: 1233333333333333333 Process finished with exit code 0
类的专有方法:
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__:乘方
运算符重载:
class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): print(self.a,type(self.a)) print(self.b,type(self.b)) return 'Vector (%d, %d)' %(self.a, self.b) def __add__(self, other): print(self.a,type(self.a)) print(self.b,type(self.b)) return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2, 10) v2 = Vector(5, -2) print(v1 + v2)
运算结果:
Vector (7, 8)
面向对象的特性:封装.继承.多态
封装:
顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
将内容封装到某处
从某处调用被封装的内容
#----------------封装---------------- class Person: def __init__(self,name,age,weight): #构造方法,创建对象时自动执行 self.Name = name self.Age = age self.Weight = weight def chi(self): self.Weight = self.Weight + 2 print(self.Weight) def jianshen(self): self.Weight = self.Weight - 1 print(self.Weight) # 根据Person创建对象 # 自动执行Personl类的__init__方法 o1 = Person('小明',22,120) #将小明和22,120分别封装到name,age,weight属性中 # 实例化 o1.jianshen() o1.chi()
运行结果:
119 121
继承:
面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。
# ---------------继承----------------- class Animals: def chi(self): print(self.name + "\t吃") def he(self): print(self.name + "\t喝") def piao(self): print("嫖娼-1") class Uncle: def du(self): print("赌博") def piao(self): print("嫖娼-2") class Dog(Animals,Uncle): def __init__(self,name): self.name = name def jiao(self): print(self.name + "\t汪汪汪~") alex = Dog("李杰") alex.piao()
运行结果:
嫖娼-1
所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。
多继承:
Python的类可以继承多个类,Java和C#中则只能继承一个类
Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
#经典类
class D: def bar(self): print 'D.bar' class C(D): def bar(self): print 'C.bar' class B(D): def bar(self): print 'B.bar' class A(B, C): def bar(self): print 'A.bar' a = A() # 执行bar方法时 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错 # 所以,查找顺序:A --> B --> D --> C # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了 a.bar()
#新式类 class D(object): def bar(self): print 'D.bar' class C(D): def bar(self): print 'C.bar' class B(D): def bar(self): print 'B.bar' class A(B, C): def bar(self): print 'A.bar' a = A() # 执行bar方法时 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错 # 所以,查找顺序:A --> B --> C --> D # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了 a.bar()
多态:
python不支持多态
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法
在类地内部,使用def关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 slef.__private_methods。