继承

1.什么是继承?
  继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类。

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

2.继承的作用?
  减少代码的冗余。

3.如何实现继承?
  1) 先确认谁是子类,谁是父类。
  2) 在定义类子类时, 子类名(父类名)。

# 父类
class Father1:
x = 1
pass class Father2:
pass class Father3:
pass # 子类
class Sub(Father1, Father2, Father3):
pass # 子类.__bases__ 查看父类
print(Sub.__bases__)
print(Sub.x)

寻找继承关系

- 如何寻找继承关系:
  - 确认谁是子类
    - 胡晨阳对象 ---> 人子类 ---> 动物父类
    - 猪坚强对象 ---> 猪子类 ---> 动物父类
    - 哈士奇对象 ---> 狗子类 ---> 动物父类

    - 人、猪、狗 都是子类

  - 确认谁是父类
    - 动物类是父类

    - 得先抽象,再继承
      - 抽取对象之间相似的部分,总结出类
      - 抽取类之间相似的部分,总结出父类。

继承可以解决代码冗余问题

# 老男孩人类
class OldboyPeople:
school = 'oldboy'
country = 'China' def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex # 老师类
class OldboyTeacher(OldboyPeople):
# school = 'oldboy'
# country = 'China' # def __init__(self, name, age, sex):
# self.name = name
# self.age = age
# self.sex = sex # 老师修改分数
def change_score(self):
print(f'老师 {self.name} 正在修改分数...') # 学生类
class OldboyStudent(OldboyPeople):
# school = 'oldboy'
# country = 'China'
#
# def __init__(self, name, age, sex):
# self.name = name
# self.age = age
# self.sex = sex
# 学生选择课程
def choose_course(self):
print(f'学生 {self.name} 正在选择课程...') stu1 = OldboyStudent('YJG', 50, 'female')
print(stu1.school, stu1.name, stu1.age, stu1.sex)
tea1 = OldboyTeacher('大脸', 75, 'female')
print(tea1.school, tea1.name, tea1.age, tea1.sex)

注意: 程序的执行顺序是由上到下,父类必须定义在子类的上方。
- 在继承背景下,对象属性的查找顺序:
  1.先从对象自己的名称空间中查找
  2.对象中没有,从子类的名称空间中查找。
  3.子类中没有, 从父类的名称空间中查找,若父类没有,则会报错!

class Goo:
x=10 class Foo(Goo):
X=100 foo_obj = Foo()
print(foo_obj.x) #
print(foo_obj.__dict__) # {}
print(Foo.__dict__) # {'__module__': '__main__', 'X': 100, '__doc__': None}
print(Goo.__dict__) # {'__module__': '__main__', 'x': 10, '__dict__':
# <attribute '__dict__' of 'Goo' objects>, '__weakref__': <attribute '__weakref__' of 'Goo' objects>, '__doc__': None} foo_obj.x = 1000
print('子类的名称空间',Foo.__dict__) # 子类的名称空间 {'__module__': '__main__', 'X': 100, '__doc__': None}
print('对象的名称空间',foo_obj.__dict__) # 对象的名称空间 {'x': 1000}

派生:

  指的是子类继承父类的属性与方法,并且派生出自己独有的属性与方法。
  若子类中的方法名与父类的相同,优先用子类的。

# 父类
class Foo:
def f1(self):
print('from Foo.f1...') def f2(self): # self ---> bar_obj
print('from Foo.f2...')
# bar_obj.f1() ---> 对象自己找 ---> Bar ---> Foo
self.f1()  # 对象的f1,而非类的f1 # 子类
class Bar(Foo): # 重写
def f1(self):
print('from Bar.f1..') def func(self):
print('from Bar.func...') # bar_obj = Bar()
# bar_obj.f1() # from Bar.f1..
# bar_obj.func() # from Bar.func...
# bar_obj.f2() # from Foo.f2... # 派生后继承关系查找验证:
bar_obj = Bar()
'''
结果1:
from Foo.f2...
from Bar.f1...
'''
bar_obj.f2()

- 子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法。

#方式一:
class OldboyPeople:
school = 'oldboy'
def __init__(self, name, age, sex): # self == tea1, name == 'tank', age == 17, sex == 'male'
self.name = name
self.age = age
self.sex = sex
class OldboyTeacher(OldboyPeople):
# tea1, 'tank', 17, 'male', 15000000
def __init__(self, name, age, sex, sal):
# self.name = name
# self.age = age
# self.sex = sex
# 类调用类内部的__init__,只是一个普通函数
# OldboyPeople.__init__(tea1, 'tank', 17, 'male')
OldboyPeople.__init__(self, name, age, sex)
self.sal = sal
def change_score(self):
print(f'老师 {self.name} 修改分数...') class OldboyStudent(OldboyPeople): def __init__(self, name, age, sex, girl):
OldboyPeople.__init__(self, name, age, sex)
self.girl = girl def choose_course(self):
print(f'学生 {self.name} 选择课程...') tea1 = OldboyTeacher('tank', 17, 'male', 15000000)
print(tea1.name, tea1.age, tea1.sex, tea1.sal) stu1 = OldboyStudent('姚玉鑫', 28, 'male', '凤姐')
print(stu1.name, stu1.age, stu1.sex, stu1.girl)
# 方式二:
class OldboyPeople:
school = 'oldboy'
# self == tea1
def __init__(self, name, age, sex): # self == tea1, name == 'tank', age == 17, sex == 'male'
self.name = name
self.age = age
self.sex = sex class OldboyTeacher(OldboyPeople):
# tea1, 'tank', 17, 'male', 15000000
def __init__(self, name, age, sex, sal):
# super() ---> 特殊的对象 ---> 对象.属性 ---> 父类的名称空间
# 会将调用类传入的对象当做第一个参数传给__init__()
super().__init__(name, age, sex)
self.sal = sal def change_score(self):
print(f'老师 {self.name} 修改分数...') class OldboyStudent(OldboyPeople): def __init__(self, name, age, sex, girl):
super().__init__(name, age, sex)
self.girl = girl
def choose_course(self):
print(f'学生 {self.name} 选择课程...') tea1 = OldboyTeacher('tank', 17, 'male', 15000000)
print(tea1.name, tea1.age, tea1.sex, tea1.sal) stu1 = OldboyStudent('姚玉鑫', 28, 'male', '凤姐')
print(stu1.name, stu1.age, stu1.sex, stu1.girl)

经典类与新式类: (了解)
  - 工作中遇不到
  - 面试有可能会问

- 新式类:
  1.凡是继承object的类或子孙类都是新式类。
  2.在python3中所有的类都默认继承object。

- 经典类:
  1.在python2中才会有经典类与新式类之分。
  2.在python2中,凡是没有继承object的类,都是经典类。

调用mro返回的是一个继承序列: (了解知识点)
super的继承顺序严格遵循mro继承序列。

super严格遵循mro继承顺序

调用mro返回的是一个继承序列: (了解知识点)
  super的继承顺序严格遵循mro继承序列。

class Father1:
x = 10
pass class Father2:
x=20
pass # 多继承的情况下: 从左到右
class Sub(Father1,Father2):
# 注意: __int__ 不是 __init__
def __init__(self):
print(super().__delattr__) print(Sub.mro()) # 显示继承顺序
# [<class '__main__.Sub'>, <class '__main__.Father1'>, <class '__main__.Father2'>, <class 'object'>]
obj=Sub() # <method-wrapper '__delattr__' of Sub object at 0x0000000009B758D0>
print(object)

在python3中提供了一个查找新式类查找顺序的内置方法.
  mro(): 会把当前类的继承关系列出来。

class Father1:
x = 10
pass class Father2:
x=20
pass # 多继承的情况下: 从左到右
class Sub(Father1,Father2):
# 注意: __int__ 不是 __init__
def __init__(self):
print(super().__delattr__) print(Sub.mro()) # 显示继承顺序
# [<class '__main__.Sub'>, <class '__main__.Father1'>, <class '__main__.Father2'>, <class 'object'>]
obj=Sub() # <method-wrapper '__delattr__' of Sub object at 0x0000000009B758D0>
print(object)

在python3中提供了一个查找新式类查找顺序的内置方法.
  mro(): 会把当前类的继承关系列出来。

# 注意: super()会严格按照mro列表的顺序往后查找
class A:
def test(self):
print('from A.test')
super().test() # 调用对象的父级,非A类的父级 class B:
def test(self):
print('from B.test') class C(A, B):
pass c = C()
# 检查super的继承顺序
print(C.mro()) # 去A找,有的话打印,然后super又执行了test,根据mro中查找打印B类中test。
c.test()
'''
from A.test
from B.test
'''

多继承情况下造成 “钻石继承”

  mro的查找顺序:
    - 新式类:
      - 广度优先:从左面第一条链往后查找,如果找到公共继承对象,跳过往右一条链继续往后查找

    - 经典类:
      - 深度优先:从左面第一条链往后查找,一直查到低,再往右从第二条一直查到底...

面试注意细节:
  - 遇到一个技术 知道是什么,但是不会用,一定要贬低这个技术,觉得很简单,让面试官误以为你很会。
  - 遇到一个技术,不知道是什么,要说我见过,但是忘记怎么用了,我博客里面,回头找一下就行了

# 了解:
# 新式类:
class A(object):
def test(self):
print('from A')
pass
class B(A):
def test(self):
print('from B')
pass
class C(A):
def test(self):
print('from C')
pass
class D(B):
# def test(self):
# print('from D')
pass
class E(C):
def test(self):
print('from E')
pass
class F(D,E):
# def test(self):
# print('from F')
pass
# F-->D-->B-->E-->C-->A-->object
print(F.mro())
obj=F()
obj.test() # from B

继承json模块中JSONEncoder,并派生出新的功能。

import json
from datetime import date, datetime # 在原来json模块中可序列化的数据类型优先
# <class 'datetime.datetime'> date
# print(type(datetime.now()))
#
# dict1 = {
# # 'time1': str(datetime.now())
# 'time1': datetime.now()
# }
#
# res = json.dumps(dict1)
# print(res) # 'datetime' is not JSON serializable class MyJson(json.JSONEncoder):
# datetime.now() ---> o
def default(self, o):
# isinstance: 判断一个对象是否是一个类的实例
if isinstance(o, datetime): # True
return datetime.strftime(o, '%Y-%m-%d %X') else:
return super().default(self, o) dict1 = {
# 'time1': str(datetime.now())
'time1': datetime.now(),
'name': 'tank'
} # 指定自定义的一个MyJson 派生类
# cls=自定义的类
res = json.dumps(dict1, cls=MyJson)
print(res) # {"time1": "2019-11-27 14:24:39", "name": "tank"}

python基础语法15 面向对象2 继承,多态,继承json模块中JSONEncoder,并派生出新的功能的更多相关文章

  1. python基础语法17 面向对象4 多态,抽象类,鸭子类型,绑定方法classmethod与staticmethod,isinstance与issubclass,反射

    多态 1.什么是多态? 多态指的是同一种类型的事物,不同的形态. 2.多态的目的: “多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字). 多 ...

  2. python基础语法_3面向对象

    http://www.runoob.com/python3/python3-class.html https://www.imooc.com/learn/317 慕课网:987809563@qq.co ...

  3. python基础语法19 面向对象总结,pickle保存对象注意事项

    面向对象的三大特性: 继承,封装,多态 多态的三种表现形式:鸭子类型,继承父类,继承抽象类 pickle保存对象注意事项 class Foo: y = 20 def __new__(cls, *arg ...

  4. python基础语法14 面向对象

    面向对象 1.什么是面向对象? 面向对象是一门编程思想! - 面向过程编程思想: 核心是 “过程” 二字,过程指的是解决问题的步骤,即先干什么再干什么! 基于该编程思想编写程序,就好比在设计一条工厂流 ...

  5. python基础语法20 面向对象5 exec内置函数的补充,元类,属性查找顺序

    exec内置函数的补充 exec: 是一个python内置函数,可以将字符串的代码添加到名称空间中; - 全局名称空间 - 局部名称空间 exec(字符串形式的代码, 全局名称空间, 局部名称空间) ...

  6. python基础语法16 面向对象3 组合,封装,访问限制机制,内置装饰器property

    组合: 夺命三问: 1.什么是组合? 组合指的是一个对象中,包含另一个或多个对象. 2.为什么要用组合? 减少代码的冗余. 3.如何使用组合? 耦合度: 耦: 莲藕 ---> 藕断丝连 - 耦合 ...

  7. Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)

    Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理) 一丶封装 , 多态 封装:            将一些东西封装到一个地方,你还可以取出来( ...

  8. python基础语法及知识点总结

    本文转载于星过无痕的博客http://www.cnblogs.com/linxiangpeng/p/6403991.html 在此表达对原创作者的感激之情,多谢星过无痕的分享!谢谢! Python学习 ...

  9. Python 基础语法(三)

    Python 基础语法(三) --------------------------------------------接 Python 基础语法(二)------------------------- ...

随机推荐

  1. 仅逗oier们一笑(不定期更新中)(update.2019年12月8日)

    CCF的正确解释: //部分来自:朝阳的二愣子的CSDN博客.ydclyq 的博客 .拱垲的博客.Randolph's Blog. 编译下列程序,会有意想不到的惊喜哦(注意打开声音): #includ ...

  2. 树形DP(超详细!!!)

    一.概念 1.什么是树型动态规划 树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺 ...

  3. LOJ 6240. 仙人掌

    我尽力写一篇比较详细的题解.... LOJ 6240. 仙人掌 我先来给你安利一个题 [BZOJ3451]Tyvj1953 Normal (DSU/点分治+NTT/FFT) 同样的,我们计算每一个点对 ...

  4. 别傻傻不知道 == 和 equals 的区别【面试系列】

    ​ 关于这个问题,一般初中级面试中都会遇到,还记得我当初实习找工作的时候也遇到了这个问题,现在都还记得自己是怎么回答的:== 是基本类型比较,equals 是对象比较,不懂 hashCode,想起来简 ...

  5. 基于Kafka的实时计算引擎如何选择?Flink or Spark?

    1.前言 目前实时计算的业务场景越来越多,实时计算引擎技术及生态也越来越成熟.以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象.那么,今天就来聊一聊基于Kafka的实时计算引 ...

  6. 改写URL的查询字符串QUERY_STRING[URL重定向问号问题](转)

    查询字符串是指URL请求中"问号"后面的部分.比如,http://mysite/?foo=bar 中粗体部分就是查询字符串,其中变量名是foo,值是bar. 'last|L' (最 ...

  7. 使用python把gdb格式的文本文件转为utf-8的格式

    # coding=utf-8 from os import listdir if __name__ =="__main__": d=u"D:\\files\\" ...

  8. mysql中的回表查询与索引覆盖

    了解一下MySQL中的回表查询与索引覆盖. 回表查询 要说回表查询,先要从InnoDB的索引实现说起.InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Sec ...

  9. 【BZOJ3328】PYXFIB(单位根反演,矩阵快速幂)

    [BZOJ3328]PYXFIB(单位根反演,矩阵快速幂) 题面 BZOJ 题解 首先要求的式子是:\(\displaystyle \sum_{i=0}^n [k|i]{n\choose i}f_i\ ...

  10. 【学习笔记】C#中的泛型和泛型集合

    一.什么是泛型? 泛型是C#语言和公共语言运行库(CLR)中的一个新功能,它将类型参数的概念引入.NET Framework.类型参数使得设计某些类和方法成为可能,例如,通过使用泛型类型参数T,可以大 ...