浅谈Python中的继承


Posted in Python onJune 19, 2020

继承

Python 中所有的类都是object类的子类,而object 继承自type

继承分为 接口继承和实现继承

接口继承:使用父类的接口名,子类重写这个方法。尽可能的继承接口类,在子类中实现方法,鼓励对接口类的多继承,这样遵循接口隔离原则,有利于归一化设计,不提倡对抽象类进行多继承

实现继承:子类不需要实现任何东西,直接使用父类接口和实现会增强代码的耦合性,不推荐使用。

一些细节

类继承最终要被实例化,我们多数时候使用的还是对象而不是类。因此我们还是来一点点看继~

继承的过程

承仅仅是一种代码复用的手段,并不会讲代码全部的加载到子类的空间中,方法依然属于父类。下面的例子能看到,Cat.func 依然是 Animal 的,更近一步的理解,func 也仅仅是func,它只是被绑定到了类 Animal上而已,类 只是能帮我们找到这个函数,子类通过父类找到这个函数就完了~ 。

class Animal(object):

  def func(self):
    print("Animal.func")


class Dog(Animal):

  def func(self):
    print('Dog.func')


class Cat(Animal):
  """ No func~ """


print(Animal.func)  # <function Animal.func at 0x103f79620>
print(Cat.func)  # <function Animal.func at 0x103f79620>
print(Dog.func)  # <function Dog.func at 0x104073510>

实例化的过程

实例化过程中属性和方法并不会出现在实例的空间里。它们依然属于类本身,对象也只是能找到他们,然后调用他们。但是当修改对象的属性时,会在对象的空间中创建同名的属性。这是属于对象的属性。复杂的继承其本质也是一样的。

class Animal(object):

  def tell(self):
    print('self.name:%s Animal.name %s ' % (id(self.name), id(Animal.name)))

  name = 'Animal'


class Cat(Animal):
  """ No func~ """

  def tell(self):
    super().tell()
    print('self.name %s Cat.name %s '% (id(self.name), id(Cat.name)))

cat = Cat()
cat.tell()
cat.name = 'django'
cat.tell()

# self.name:4473398472 Animal.name 4473398472 
# self.name 4473398472 Cat.name 4473398472 
# self.name:4474859736 Animal.name 4473398472 
# self.name 4474859736 Cat.name 4473398472

单继承

越靠近本类的方法会覆盖祖辈的方法,这叫方法的覆盖或重写 原理是 Python的属性检索机制 从内层命名空间往外查询

class MyClass(object):
  """
  A simple example class
  """
  MyClassName = 'MyClass'
  name = 'MyClass'

  def func(self):
    print("This is {}".format(self.__class__.name))

  def get_name(self):
    print(self.name)

class MySonClass(MyClass):

  MySonClass = 'MySonClass'
  name = 'MySonClass' # 属性的重写

  def get_name(self):
    super().get_name()
    print('我重写了父类的get_name方法,上面是父类的方法,我来自子类!')


person1 = MyClass()
person2 = MySonClass()

person1.func()
person2.func()  # 方法的实现继承 自己没有,会直接调用父类的方法。但是使用的属性还是自己的。
print('*'*40)
person1.get_name()
person2.get_name()  # 方法的接口继承,在子类中重写了这个方法。


# 结果	
#------------------------------ 
# This is MyClass
# This is MySonClass
# ****************************************
# MyClass
# MySonClass
# 我重写了父类的get_name方法,上面是父类的方法,我来自子类!

多继承

就形式上来说,类的继承列表可以是一个,也可以是多个,当继承列表只有一个类时,也就是只有一个父类时,称为单继承,大于一个类,就称为多继承。

新式类的继承方式为 广度优先继承 经典类的继承方式为 深度优先继承。

类继承的顺序可以使用类的 __mro__ 方法查看。

钻石继承

class A(object):
  m = 'a'
class B(A):
  m = 'b'
class C(A):
  m = 'c'
class D(B,C):
  # m = 'd'
  pass
x = D()
print(x.m)

# D 的实例化对象如果获取 m 属性会优先的寻找自己的命名空间,查找顺序为 D -> B -> C -> A

super()方法

语法super(类,实例化对象).父类的方法

当super()方法在类的内部使用时候,甚至不需要任何的参数

当在多继承中使用super()方法的时候执行的不再是父类的方法了 而是和mro中上一级的方法

super()为了解决多继承中,初始化方法被重复调用的问题。(当使用类名.方法名的时候)

当使用super()方法执行“父类” (__mro__ 方法的上一个类) 的方法

# 钻石继承中的 重复调用问题
# 注意 继承的查找顺序~ 使用super()将按照 mro 顺序执行

class Grand(object):
  def __init__(self, name):
    self.name = name
    print("class Grand ")


class SonLeft(Grand):
  def __init__(self, age, name):
    self.age = age
    Grand.__init__(self, name) # 注释调 跑一跑 看一看
    # super().__init__(age, name)
    print("class SonLeft")


class SonRight(Grand):
  def __init__(self, gender, name):
    self.gender = gender
    Grand.__init__(self, name) # 注释调 跑一跑 看一看
    # super().__init__(name)
    print("class SonRight")


class GrandSon(SonLeft, SonRight):
  def __init__(self, name, age, gender):
    # super().__init__(age, name)
    SonLeft.__init__(self, age, name) # 注释调 跑一跑 看一看
    SonRight.__init__(self, gender, name) # 注释调 跑一跑 看一看
    self.gender = gender

grand_son = GrandSon("Monkey", 18, "男")

以上就是浅谈Python中的继承的详细内容,更多关于Python 继承的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现周期性抓取网页内容的方法
Nov 04 Python
Python Requests 基础入门
Apr 07 Python
Python实现字符串反转的常用方法分析【4种方法】
Sep 30 Python
Python面向对象编程基础解析(二)
Oct 26 Python
浅谈django url请求与数据库连接池的共享问题
Aug 29 Python
利用python实现逐步回归
Feb 24 Python
Python 中由 yield 实现异步操作
May 04 Python
python中pandas库中DataFrame对行和列的操作使用方法示例
Jun 14 Python
Python requests库参数提交的注意事项总结
Mar 29 Python
python实现求纯色彩图像的边框
Apr 08 Python
python实现图片批量压缩
Apr 24 Python
pytorch 实现在测试的时候启用dropout
May 27 Python
python程序需要编译吗
Jun 19 #Python
python中round函数如何使用
Jun 19 #Python
keras实现theano和tensorflow训练的模型相互转换
Jun 19 #Python
Keras 切换后端方式(Theano和TensorFlow)
Jun 19 #Python
python中怎么表示空值
Jun 19 #Python
Python调用OpenCV实现图像平滑代码实例
Jun 19 #Python
使用OpenCV对车道进行实时检测的实现示例代码
Jun 19 #Python
You might like
批量去除PHP文件中bom的PHP代码
2012/03/13 PHP
PHP 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
2014/06/12 PHP
php制作简单模版引擎
2016/04/07 PHP
php实现URL加密解密的方法
2016/11/17 PHP
phpmailer绑定邮箱的实现方法
2016/12/01 PHP
PHP中将一个字符串部分字符用星号*替代隐藏的实现代码
2019/09/08 PHP
js最简单的拖拽效果实现代码
2010/09/24 Javascript
解析js如何获取当前url中的参数值并复制给input
2013/06/23 Javascript
easyui取消表单实时验证,提交时统一验证的简单实例
2016/11/07 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
2017/02/24 Javascript
EasyUI的DataGrid每行数据添加操作按钮的实现代码
2017/08/22 Javascript
angularjs实现过滤并替换关键字小功能
2017/09/19 Javascript
dropload.js插件下拉刷新和上拉加载使用详解
2017/10/20 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
2018/09/27 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
浅谈vue中get请求解决传输数据是数组格式的问题
2020/08/03 Javascript
ant design pro中可控的筛选和排序实例
2020/11/17 Javascript
让Python更加充分的使用Sqlite3
2017/12/11 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
2018/05/16 Python
python for循环输入一个矩阵的实例
2018/11/14 Python
详解python中的hashlib模块的使用
2019/04/22 Python
Pycharm使用远程linux服务器conda/python环境在本地运行的方法(图解))
2019/12/09 Python
Python基于Dlib的人脸识别系统的实现
2020/02/26 Python
20行Python代码实现视频字符化功能
2020/04/13 Python
Python测试框架:pytest学习笔记
2020/10/20 Python
美国玩具公司:U.S.Toy
2018/05/19 全球购物
Bulk Powders意大利:运动补充在线商店
2019/02/09 全球购物
小学毕业感言50字
2014/02/16 职场文书
体育教师求职信
2014/05/24 职场文书
高中班级口号
2014/06/09 职场文书
2014年仓库保管员工作总结
2014/12/03 职场文书
考试作弊检讨书
2015/01/27 职场文书
2015年幼儿园中班开学寄语
2015/05/27 职场文书
2015年物流客服工作总结
2015/07/27 职场文书
您对思维方式了解多少?
2019/12/09 职场文书
如何避免mysql启动时错误及sock文件作用分析
2022/01/22 MySQL