继承和派生

目录1. 继承1. 什么是继承2. 为什么要继承3. 怎么继承,如何实现继承4. 继承后,对象的属性的搜索顺序5. 新式类和经典类(面试会问)1. 新式类2. 经典类3. mro() / __class__ / __name__ 方法4. 钻石继承(也称为菱形继承)(1) 新式类的钻石继承顺序(2) 经典类的钻石继承顺序2. 继承的实例3. 派生1. 什么是派生2. 子类派生出新的属性,并重用父类的属性

1. 继承

1. 什么是继承

继承:就是新建类的方法,新建的类称之为子类或者派生类,子类继承的类叫做父类,也称之为基类或超类。简单的说:一个类可以得到另一个类名称空间中的属性和方法的这个特性,这种特性就是通过继承来实现的

继承的特征:

子类可以继承父类的属性(特征和技能),并且可以派生出自己的属性(特征和技能)

在python中,一个子类可以继承多个父类,其它编程语言只能一个子类继承一个父类(面试可能会问)

2. 为什么要继承

继承的目的就是为了减少代码冗余(减少重复代码)

3. 怎么继承,如何实现继承

首先要确定好谁是子类谁是父类

在定义类时,子类 + () ,()内写父类的名字,实现子类继承父类

# 子类B继承父类A

class A:

pass

class B(A):

pass

print(B.__bases__) #查看B继承的父类们,以元组飞形式打印出各父类

print(B.__bases__[0].__dict__) # 查看B的第一个父类的属性

什么是抽象?

抽象指的是抽取相似的部分,称之为抽象.

继承的关系:

对象是特征与技能的结合体.

类是一系列对象相同的特征与技能的结合体.

继承是一系列类相同的特征与技能的结合体.

4. 继承后,对象的属性的搜索顺序

下面的查找中,只要找到了就不会继续找了

先从对象的名称空间中查找该属性

若对象的名称空间中没有,就会去子类的名称空间中查找

若子类中没有,就去父类中查找,并且按照父类的继承顺序查找。

5. 新式类和经典类(面试会问)

python2 中才会有新式类和经典类之分。

python3 中所有的类都是新式类

1. 新式类

什么是新式类:

继承object的类都称之为新式类

python3 中,子类如果不继承自定义的类,会默认继承object

2. 经典类

什么是经典类

在python2 中,凡是没有继承object 的类都是经典类

3. mro() / __class__ / __name__ 方法

mro()方法是属于object类中的方法,在多继承情况下,可以用来查看当前类的继承顺序。他返回的结果是一个元组。注意要索引取值。

__class__ 是对象的方法,可以获得实例化该对象的类。

__name__ 一种通用的方法,类/函数 通过.__name__可以获取类/函数的 名字。

4. 钻石继承(也称为菱形继承)

在多继承的情况下会形成钻石继承

钻石继承的继承顺序:分为 新式类 和 经典类 的继承顺序

(1) 新式类的钻石继承顺序

新式类的钻石继承顺序为 : 广度优先。

它的特点是按一个子类的继承时括号内的书写顺序,从左到右依次,(如子类1(A,D,G...)),先继承:

第一个父类A——》A的父类B——》B的父类C——》。。。

第二个父类D——》D的父类E——》E的父类F——》。。。

。。。

但最后继承顶层的父类,再继承object类

(2) 经典类的钻石继承顺序

经典类的钻石继承顺序为: 深度优先

它的特点是按一个子类的继承时括号内的书写顺序,从左到右依次,(如子类1(A,D,G...)),先继承:

第一个父类A——》A的父类B——》B的父类C——》。。。——》顶层的父类

第二个父类D——》D的父类E——》E的父类F——》。。。——》顶层父类继承过了,到顶层的父类的最近的一个儿子类就结束继承。开始第三个父类,第三个父类也是同第二个父类一样的继承顺序。

。。。

2. 继承的实例

通过继承实现修改json模块的数据类型

import json

from datetime import date, datetime

print(json.JSONEncoder)

print(datetime.today()) # 当前时间

print(date.today()) # 当前日期

# 开发者的角度: 直接转成str

# dict1 = {

# 'name': 'tank',

# 'today': str(datetime.today()),

# 'today2': str(date.today())

# }

#

# res = json.dumps(dict1)

# print(res)

# isinstance:

# python内置的函数,可以传两个参数,判断参数一是否式参数二的一个实例.

*********************继承的使用***********************

# 开源者的角度: 修改json源码

class MyJson(json.JSONEncoder):

def default(self, o):

# 子类派生的功能

# 判断o是否式datetime的一个实例

if isinstance(o, datetime):

return o.strftime('%Y-%m-%d %X')

elif isinstance(o, date):

return o.strftime('%Y-%m-%d')

else:

# 继承父类的default方法的功能

return super().default(self, o)

dict1 = {

'name': 'tank',

'today': datetime.today(),

'today2': date.today()

}

res = json.dumps(dict1, cls=MyJson) # cls=None,默认指向的是原json的JSONEncoder

print(res)

3. 派生

1. 什么是派生

派生指的是子类继承父类的属性,并且产生自己新的属性

子类派生出新的属性,若与父类的属性相同,则以子类的为准。

2. 子类派生出新的属性,并重用父类的属性

问题:子类继承了父类的__init__属性,但还需要添加自己的一些新的属性

解决方法:

注意下面的两种方法不要混合使用

方法一:

直接通过 父类.__init__(self,要重用的属性) 来实现重用父类属性

class OldboyPeople:

def __init__(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

class OldboyTeacher(OldboyPeople):

# 等级, 薪资

def __init__(self, name, age, sex, level, sal):

OldboyPeople.__init__(self, name, age, sex)

self.level = level

self.sal = sal

方法二:(比方法一,少写了self)

super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,

通过"."指向的是父类的名称空间.

class OldboyPeople:

def __init__(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

class OldboyTeacher(OldboyPeople):

# 等级, 薪资

def __init__(self, name, age, sex, level, sal):

super().__init__(name, age, sex)

self.level = level

self.sal = sal

贏字的拼音(读音)怎么读
你知道古代人是怎么喝水的吗?