继承封装&多态&抽象类&特殊方法"__init__"

继承封装

#复用

#接口 interface 只需要考虑接口,接口内部不需要考虑
#实现 implementation 接口内部的东西

#封装 设计一个高性能的implementation 和简单的interface,使得别人能快速上手**

#继承

继承

from person import person, gender 
class employee(person):#从person继承已有的成果
    def __init__(self,emplno,idno,name):
        super(employee,self).__init__(idno,name)#super上一级,实现父类person的构造函数‘__int__‘那个
        #等价于 person.__int__(self,idno,name)
        #接下来描述不同的地方
        self.semployeeno = emplno
        self.sjobtitle = ''
        self.sdepartment = ''
        self.weeksalary = 0
    def work(self):
        print('i am a',self.sjobtitle)
    def speak(self):
        super().speak()#调用父辈的speak方法
        print('employee::speak():')
        print('i am happy to work for you')

#实例化employee
yangchen=employee('3180101','330327','yangchen')
yangchen.gender = gender.male
yangchen.sdepartment = 'study'
yangchen.sjobtitle = 'student'
yangchen.weeksalary = 2000

#employee 杨晨 动作
yangchen.work()#使用函数def work(self):,但是没有给self,yangchen就是隐含的self
yangchen.speak()
print(yangchen.semployeeno)
i am a student
person::speak():
i am yangchen, nice to meet you
employee::speak():
i am happy to work for you
3180101

多态 polymorphism & 抽象类 abstract class

ppt内部结构为例

抽象类

from abc import ABC,abstractmethod #Abstract Base Classes
class shape(ABC):
    @abstractmethod
    def draw(self):
        pass
    @abstractmethod
    def getSize(self):
        pass
#@abstractmethod代表shape是基类,抽象类,无法被实例化
#a = shape(%%javascript将会提示:Can't instantiate abstract class shape with abstract methods draw, getSize

class triangle(shape):#triangle从shape继承
    def __int__(self):
        self.point0 = (0,0)
        self.point1 = (1,1)
        self.point2 = (0,1)
    
    def draw(self):#自己画自己
        print('triangle::draw')
    
    def getSize(self):
        pass #detail omitted内容重载了,但是pass不执行
    
    def getArea(self):
        return 0

class circle(shape):#triangle从shape继承
    def __int__(self):
        self.ptCenter = (0,0)
        self.iRadius = 0
    
    def draw(self):
        print('circle::draw')
    
    def getSize(self):
        pass #detail omitted内容重载了,但是pass不执行
    
    def getArea(self):
        return 0

#实例化类
t1 = triangle()
t2 = triangle()
c1 = circle()
c2 = circle()
#pptx模拟一个ppt,将界面元素组织在列表中
pptx = [t1,t2,c1,c2]

错误的遍历元素,全部画出

假如借助外部方法画出pptx中的所有元素,每个类型都要画,利用for循环
而且外部程序必须得要先知道pptx内部所有的数据结构,违反隐藏内部原则

for x in pptx:
        if __name__ == '__main__':
            if type(x) == traingle:
                drawline(x.point0,x.point1)
            elif type(x) == circle:
                drawcircle()
            elif
            #...

正确的遍历元素,全部画出

前面在定义triangle和circle类型时,内置了draw函数,可以自己画自己,因此draw是对象的一个对自己的动作,使用x.draw()就可以实现画自己

和上面错误的方法比较,x.draw就是一个interface,implementation都在内部解决,外部不需要明白原理

def renderDocument(pptx):
    for x in pptx:
        x.draw()
renderDocument(pptx)
triangle::draw
triangle::draw
circle::draw
circle::draw

多态

上面的pptx = [t1,t2,c1,c2]就称为多态。

pptx列表里的t1,c1…,并不知道他们是什么类型,比如t1是triangle类,c1是circle类。
但是把他们当作shape类型来用,好像执行shape.triangle()(实际shape是抽象类无法执行)

具体到执行动作时,每一个x,又会执行各自类的draw()

def renderDocument(pptx):
    for x in pptx:
        x.draw()
renderDocument(pptx)

多态的优点

假如需要增添rectangle类,和circle、triangle并列。

再执行遍历元素全部画出图形

pptx = [t1,t2,c1,c2]
def renderDocument(pptx):
    for x in pptx:
        x.draw()
renderDocument(pptx)

只需要增加如下部分r1 = rectangle(), pptx = [t1,t2,c1,c2,r1]

总结

多态的好处就是,当我们需要传入更多的子类,例如新增 rectangle 等时,我们只需要继承 shape 类型就可以了,而draw()方法既可以直不重写(即使用shape的),也可以重写一个特有的。这就是多态的意思。

调用方只管调用,不管细节,而当我们新增一种shape的子类时,只要确保新方法编写正确,而不用管原来的代码。这就是著名的**“开闭”原则**:

对扩展开放(Open for extension):允许子类重写方法函数
对修改封闭(Closed for modification):不重写,直接继承父类方法函数

套娃继承

这是一个套娃
首先看def __init__(self):,当实例化D时,首先执行初始化里的super(D,self).__init__(),等价于C.__init__()
C.__init__() 将执行print('C is init')super(C,self).__init__(),又等价于B.__init__()
…最终D的def __init__(self):执行ABCD全部的def __init__(self)

而且D继承了ABCD所有的方法,method1,2,3,4


几个与继承链有关的方法和属性
issubclass(D,A)
D.__bases__
isinstance(d,D)
d.__class__

class A:
    def __init__(self):
        print('A is init')
    def method1(self):
        print('method 1 ok')

class B(A):
    def __init__(self):
        super(B,self).__init__()
        print('B is init')
    def method2(self):
        print('method 2 ok')

class C(B):
    def __init__(self):
        super(C,self).__init__()
        print('C is init')
    def method3(self):
        print('method 3 ok')

class D(C):
    def __init__(self):
        super(D,self).__init__()
        print('D is init')
    def method4(self):
        print('method 4 ok')

d= D()
print(issubclass(D,A))#判断D是不是A的子类
print(D.__bases__)#加两个下划线是系统的,特殊定义,自己不要用。可以查D的父类是什么
print(isinstance(d,D))#d是不是D的实例
print(d.__class__)
A is init
B is init
C is init
D is init
True
(<class '__main__.C'>,)
True
<class '__main__.D'>

多重继承

继承多个父类,所有的属性和方法都可以继承
注意子类中多个父类如何初始化

 def __init__(self):
        super().__init__()#只能初始化一个父类对象,左边第一个
        #更好的是Person.__init__(self)
        TaxPayer.__init__(self)#只能显式初始化,self是employee的实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PmdZGfQR-1587117986376)(attachment:%E7%BB%A7%E6%89%BF2.png)]

class Person:
    def __init__(self):
        self.sName = ''
        self.sId = ''
        print('Person::__init__().')
    
    def eat(self,weight):
        print('person::eat():',weight,'gram of food')

class TaxPayer:
    def __init__(self):
        self.childernCount = 0
        print('TaxPayer::__init___().')
    
    def compIncomeTax(self):
        print('TaxPayer::compIncomeTax().')
        return 0
class Employee(Person,TaxPayer):
    def __init__(self):
        super().__init__()#只能初始化一个父类对象,左边第一个
        #更好的是Person.__init__(self)
        TaxPayer.__init__(self)#只能显式初始化,self是employee的实例
        self.sEmpolyeeNo = ''
        self.iWeekSalary = 0
        print('Employee::__init__()')
        
    def work(self):
        print('Employee::work().')
yang = Employee()
yang.eat(20)
yang.compIncomeTax()
yang.iWeekSalary = 2000
yang.sEmpolyeeNo = 3180101
Person::__init__().
TaxPayer::__init___().
Employee::__init__()
person::eat(): 20 gram of food
TaxPayer::compIncomeTax().

特殊方法 魔法方法

带有’__'称为特殊方法

python中特殊方法(魔术方法)是被python解释器调用的,我们自己不需要调用它们,是解释器隐含执行。我们统一使用内置函数来使用。


__init__()

初始化函数

__del__()

对象生命周期结束时调用,__del__会先执行后清除。

python解释器会在恰当的时候清除没用对象。这个恰当时候并不确定,不能假设

class person:
    def __init__(self,name ='N/A'):
        self.sName = name
        print('person::__init__')
    def __del__(self):
        print("Person::__del__")

d = person('yang'):执行构造函数
c = d 
d = None
print('-------------------------------')
c = 2 # 原本person('yang')此时不被任何对象绑定,解释器认为没有用了,生命周期结束
print('*******************************')

person::__init__
-------------------------------
Person::__del__
*******************************

方法的隐藏

方法的前面加’__'外部无法访问
eg.假如执行 hid.privateMethod(),将会提示AttributeError: 'hidden' object has no attribute 'privateMethod'

but类内部是可以访问的
eg.假如执行hid.publicMethod()将会得到this method should not be called outside

class hidden:
    'this class will show you the private method'
    def __init__(self):
        pass
    def __privateMethod(self):
        print('this method should not be called outside')
    def publicMthod(self):
        self.__privateMethod()
hid = hidden()
hid.publicMthod()
this method should not be called outside
发布了8 篇原创文章 · 获赞 0 · 访问量 21

猜你喜欢

转载自blog.csdn.net/weixin_44827144/article/details/105585854
今日推荐