Day17:面向对象进阶
一、继承相关
- 继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,
父类又可称为基类或超类,新建的类称为派生类或子类。
class Animal: def __init__(self,name,food): self.name = name self.food = food def eat(self): print('%s 吃 %s'%(self.name,self.food)) class Dog(Animal): def swim(self): print('%s is swimming'%self.name) class Bird(Animal): def fly(self): print('%s is flying'%self.name) dog = Dog('熊二','狗粮') dog.eat()
- 继承、抽象和派生
- 继承是基于抽象的结果,通过编程语言去实现它。是要先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
- 抽象只是分析和设计的过程中的一种技巧,通过抽象可以得到类。
- 派生:子类可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),
需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
- 在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,
应该是用调用普通函数的方式,此时就与调用普通函数无异了,因此即便是self参数也要为其传值。
在python3中,子类执行父类的方法也可以直接用super方法。
class Person(Animal): def __init__(self,name,blood,aggr,money): super(Person,self).__init__(name,blood,aggr,) self.money = money def attack(self,dog): dog.blood -= self.aggr class Dog(Animal): def __init__(self,name,blood,aggr,breed): super().__init__(name,blood,aggr) self.breed = breed def bite(self,person): person.blood -= self.aggr person = Person('egon',2000,300,20000) dog = Dog('alex',2000,200,'金毛')
- 接口类和抽象类
- 接口类:
- 继承有两种用途:
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)
且并未实现接口的功能,子类继承接口类,并且实现接口中的功能。
- 借用abc模块来实现接口
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self,money): pass class Wechatpay(Payment): def pay(self,money): print('微信支付了%s元'%money) p = Wechatpay()
- 归一化:
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,
使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
- 依赖倒置原则:
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;
细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。
- 抽象类
- 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。
抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
抽象类的本质还是类,指的是一组类的相似性,包括数据属性和函数属性,而接口只强调函数属性的相似性。
- 多继承问题
- 在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
- 接口隔离原则:
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
- 钻石继承
- python 的类可以继承多个类,其寻找的方式有两种:深度优先和广度优先。
- 当类是经典类时,多继承情况下,会按照深度优先的方式查找。
- 当类是新式类时,多继承情况下,会按照广度优先的方式查找。

- 在python3中,所有类默认继承object,但凡是继承了object类的子类,以及该子类的子类,都称为新式类(在python3中所有的类都是新式类)
没有继承object类的子类成为经典类(在python2中,没有继承object的类,以及它的子类,都是经典类)。

- 继承的作用
减少代码的重用
提高代码可读性
规范编程模式
二、多态相关
- 多态指的是一类事物有多种形态。例如动物有人,狗,猪等多种形态。
- 多态性:
多态性是指在不考虑实例类型的情况下使用实例, 多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,
以及根据所引用对象的不同,以不同的方式执行相同的操作。
- 鸭子类型:
多态可以理解为鸭子类型,是程序设计中的一种风格,“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,
那么这只鸟就可以被称为鸭子。”在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。
三、封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式。
- 好处:
1. 将变化隔离;
2. 便于使用;
3. 提高复用性;
4. 提高安全性;
- 封装原则:
1. 将不需要对外提供的内容都隐藏起来;
2. 把属性都隐藏,提供公共方法对其访问。
- 封装方法:
封装的方法就是在属性前面加上双下划线,即设置成私有变量或私有方法。
class Teacher: def __init__(self,name,pwd): self.name = name self.__pwd = pwd def __pwd(self): print(self.__pwd) egon = Teacher('egon',6666) print(egon._Teacher__pwd)
-这种变形需要注意的问题是:
1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N
2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形
- property属性
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值。
import math class Circle: def __init__(self,radius): #圆的半径radius self.radius=radius @property def area(self): return math.pi * self.radius**2 #计算面积 @property def perimeter(self): return 2*math.pi*self.radius #计算周长 c=Circle(10) print(c.radius) print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值 print(c.perimeter)
- 为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,
这种特性的使用方式遵循了统一访问的原则
- setter 和 deleter
class Goods: def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price @price.setter def price(self, value): self.original_price = value @price.deleter def price(self): del self.original_price obj = Goods() obj.price # 获取商品价格 obj.price = 200 # 修改商品原价 print(obj.price) del obj.price # 删除商品原价
- classmethod
类方法,当这个方法被调用时,我们用类作为第一个参数,而不是那个类的实例,你可以在函数内使用该类和它的属性,而不是特定的实例的属性。
class Classmethod_Demo(): role = 'dog' @classmethod def func(cls): print(cls.role) Classmethod_Demo.func()
- staticmethod
静态方法,不能将该函数独立的放在类外面,当这个方法被调用的时候,不会把类的实例传递给它,该函数不会依赖对象的属性或者类的属性,也没有必须传的参数
class Staticmethod_Demo(): role = 'dog' @staticmethod def func(): print("当普通方法用") Staticmethod_Demo.func()

浙公网安备 33010602011771号