1.今日内容
- 面向对象的三大特性:封装,继承,多态
- 什么是继承?
- 继承的优点
- 单继承,多继承
- 类的约束
- super的深入理解
2.具体内容
-
面向对象的三大特性:封装,继承,多态
-
封装
-
将一些东西内容装到一个地方,并可以取出来
-
类、设置静态属性,设置一些方法
-
对象、可以在其对象空间中封装一些属性
-
多态
-
一个事物产生多种形态
-
数据结构的多种状态。如一个变量,即可以被复制为一个列表,也可以被赋值为一个字符串
- Remark:而在C++或者Java等语言中,定义变量必须提前声明变量的类型,否则会报错
-
继承
-
-
什么是继承?
- 专业角度:B继承A类,B就叫做A的子类,派生类,A叫B的父级,基类,超类
- 子类可以调用父类的所有方法与属性
-
继承的优点
- 节省代码
- 增强耦合性
- 代码规范性
-
单继承,多继承
-
单继承:只有一个父类
- 从类名执行父类属性与方法
- 从对象执行父类属性与方法
class Animal(): live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print(f'self-->{self}') print('动物都需要吃饭') class Person(Animal): pass print(Person.__dict__) print(Person.live) Person.eat('xxx') p1 = Person('jik',18,'boy') print(p1.live) p1.eat() print(f'p1-->{p1}') Person.live = 'xxx' print(Person.live)
输出:
{'__module__': '__main__', '__doc__': None} 有生命的 self-->xxx 动物都需要吃饭 有生命的 self--><__main__.Person object at 0x104634ac8> 动物都需要吃饭 p1--><__main__.Person object at 0x104634ac8> xxx
Remark:
- 子类以及子类对象只能调用父类的属性以及方法,不能操作(增删改)
- 当子类与父类的方法重名时,子类会将父类的方法‘覆盖’
class Animal(): live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print(f'self-->{self}') print('动物都需要吃饭') class Person(Animal): def eat(self): print('人类需要吃饭') p1 = Person('jik',18,'boy') p1.eat()#人类需要吃饭
Remark:
- 对象查找顺同样满足‘就近原则’,并且顺序单项不可逆
当即需要执行父类方法又执行子类方法时,均需要在对象所在类的重名方法中‘加盐’
- 有两种解决方案
class Animal(): live = '有生命的' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print(f'self-->{self}') print('动物都需要吃饭') class Person(Animal): def __init__(self,name,age,sex,hobby): #方法一: Animal.__init__(self,name,age,sex) #方法二: super(Person,self).__init__(name,age,sex) super().__init__(name,age,sex) self.hobby = hobby def eat(self): print('人类都需要吃饭') super().eat() p1 = Person('jik',18,'boy','打球') p1.eat() 人类都需要吃饭 self--><__main__.Person object at 0x10d0d7b00> 动物都需要吃饭
-
多继承:存在两个或者两个以上的父类
- 经典类:所有父类不继承object,查询规则依据深度优先算法
- python2.2以前版本
- 新式类:所有父类默认继承object,查询规则依据mro算法(拓扑排序)
- Python3.0及以后版本
- 共存:
- Python2.2~2.7版本
- 经典类:所有父类不继承object,查询规则依据深度优先算法
-
-
类的约束
- 鸭子类型:两个独立的类,存在命名相同的相似功能,python中便在底层制定了一个规范,使这些功能统一,称这两个类互为鸭子类:
class Str: def index(self): pass def count(self): pass class list: def index(self): pass def count(self): pass
-
类的约束:开发规范的一种,统一编码方式,为不合规范的类与方法抛出异常
-
第一种方法:raise
class Payment: def pay(self,money): #约定俗称定义一种规范,子类要定义pay方法 raise Exception('子类必须定义此方法') class QQpay(Payment): def pay(self,money): print(f'利用qq支付了{money}') class Alipay(Payment): def pay(self,money): print(f'利用支付宝支付了{money}') class Wechatpay(Payment): def pay(self,money): print(f'利用微信支付了{money}') ///////////////////////////////// /def fukuan(self,money): / / print(f'利用微信支付了{money}') / def pay(obj,money): obj.pay(money) obj = Wechatpay() pay(obj,300) obj.fukuan(300)#报错(‘子类必须定义此方法’)
-
第二种方法:导入固定abc的固定类与固定方法
from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class QQpay(Payment): def pay(self, money): print(f'利用qq支付了{money}') class Alipay(Payment): def pay(self, money): print(f'利用支付宝支付了{money}') class Wechatpay(Payment): def fuqian(self,money): print(f'利用微信支付了{money}') obj3 = Wechatpay()
输出:
报错("Can't instantiate abstract class Wechatpay with abstract methods pay")
-
-
super的深入理解
- super():执行父类的方法,括号里两个参数,第一个参数是对象所在的mro序列中的任意一个元素(包括本类名),第二个参数是self,它会执行这个mro序列中,第一个参数(类)的下一个类
class A: def f1(self): print('in A') class Foo: def f1(self): print('in B') class Bar(A): def f1(self): print('in Bar') calss Info(Foo,Bar): def f1(self): super(Info,self).f1() super(Foo,self).f1() super(Bar,self).f1() print('in Info f1') obj = Info() print(Info.mro()) obj.f1()
输出:
[<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>] in B in Bar in A in Info f1