面向对象的三大特性:继承、封装、多态
一、python面向对象的三大特性:继承、封装、多态
封装:把很多数据封装到一个对象中。把固定功能的代码封装到一个代码代码块、函数、对象、打包成模块。这都属于封装的思想。具体的情况具体分析,比如,你写了一个很NB的函数,那这个也可以被称之为封装。在面向对象思想中,是把一些看似无关紧要的内容组合到一起统一进行存储和使用,这就是封装。
继承:子类可以自动拥有父类中除了私有属性外的其他所有内容。先有父类再有子类。在python中实现继承非常简单,在声明类的时候,在类名后面添加一个小括号,就可以完成继承关系。
多态:同一个对象,多种形态。
二、封装
封装:将内容封装到某个地方,以后再去调用被封装在某处的内容
# 创建类 class Foo(): def __init__(self,name,age): self.name = name self.age = age def detail(self): print(self.name) print(self.age) # 根据类Foo创建对象 # 自动执行Foo类的__init__方法 obj1 = Foo("agen",15) print(obj1.name) # 直接调用obj1对象的name属性 print(obj1.age) # 直接调用obj1对象的age属性 # 通过self间接调用被封装的内容 obj1.detail() # Python默认会将obj1传给self参数,所以此时方法内部的 self = obj1 # 根据类Foo创建对象 # 自动执行Foo类的__init__方法 obj2 = Foo("alex",15) print(obj2.name) # 直接调用obj1对象的name属性 print(obj2.age) # 直接调用obj1对象的age属性 # 通过self间接调用被封装的内容 obj2.detail() # Python默认会将obj1传给self参数,所以此时方法内部的 self = obj1
对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取封装的内容。
二、多态
多态:同一个对象,多种形态。python默认支持多态。(创建一个变量a=10,此时a是整数类型,通过程序让a="alex",a又变成了字符串类型,这就是多态性,同一个变量可以是多种形态)
鸭子类型:长得像鸭子,走路像鸭子,叫声也像鸭子,那么你就是鸭子。
三、类的约束
对类的约束有两种:
1、提取父类,然后在父类中定义好方法。在这个方法中什么都不用干,就抛一个异常就可以了,这样所有的子类都必须重写这个方法,否则,访问的时候出错。
2、使用元类来描述父类,在元类中给出一个抽象方方法,这样子类就不得不给出抽象方法的具体实现,也可以起到约束的效果。
第一种方法解决:
class Payment: """ 此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。 """ def pay(self,money): raise Exception("你没有实现pay方法") class QQpay(Payment): def pay(self,money): print(‘使用qq支付%s元‘ % money) class Alipay(Payment): def pay(self,money): print(‘使用阿里支付%s元‘ % money) class Wechatpay(Payment): def fuqian(self,money): print(‘使用微信支付%s元‘ % money) def pay(obj,money): obj.pay(money) a = Alipay() b = QQpay() c = Wechatpay() pay(a,100) pay(b,200) pay(c,300)
第二种方法:引入抽象类的概念处理。
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类 @abstractmethod def pay(self):pass # 抽象方法 class Alipay(Payment): def pay(self,money): print(‘使用支付宝支付了%s元‘%money) class QQpay(Payment): def pay(self,money): print(‘使用qq支付了%s元‘%money) class Wechatpay(Payment): # def pay(self,money): # print(‘使用微信支付了%s元‘%money) def recharge(self):pass def pay(a,money): a.pay(money) a = Alipay() a.pay(100) pay(a,100) # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能 q = QQpay() q.pay(100) pay(q,100) w = Wechatpay() pay(w,100) # 到用的时候才会报错 # 抽象类和接口类做的事情 :建立规范 # 制定一个类的metaclass是ABCMeta, # 那么这个类就变成了一个抽象类(接口类) # 这个类的主要功能就是建立一个规范
四、super()深入学习
super是严格按照类的继承顺序执行!!!
class A: def f1(self): print(‘in A f1‘) def f2(self): print(‘in A f2‘) class Foo(A): def f1(self): super().f2() print(‘in A Foo‘) obj = Foo() obj.f1()
class A: def f1(self): print(‘in A‘) class Foo(A): def f1(self): super().f1() print(‘in Foo‘) class Bar(A): def f1(self): print(‘in Bar‘) class Info(Foo,Bar): def f1(self): super().f1() print(‘in Info f1‘) obj = Info() obj.f1() ‘‘‘ in Bar in Foo in Info f1 ‘‘‘ print(Info.mro()) # [<class ‘__main__.Info‘>, <class ‘__main__.Foo‘>, <class ‘__main__.Bar‘>, <class ‘__main__.A‘>, <class ‘object‘>]
class A: def f1(self): print(‘in A‘) class Foo(A): def f1(self): super().f1() print(‘in Foo‘) class Bar(A): def f1(self): print(‘in Bar‘) class Info(Foo,Bar): def f1(self): super(Foo,self).f1() print(‘in Info f1‘) obj = Info() obj.f1()