浅谈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的Tornado框架对子域名和泛域名的支持
May 02 Python
python绘图方法实例入门
May 19 Python
Python中返回字典键的值的values()方法使用
May 22 Python
python利用装饰器进行运算的实例分析
Aug 04 Python
python机器学习之神经网络(三)
Dec 20 Python
Python实现的rsa加密算法详解
Jan 24 Python
详解Django-auth-ldap 配置方法
Dec 10 Python
Python告诉你木马程序的键盘记录原理
Feb 02 Python
Python键鼠操作自动化库PyAutoGUI简介(小结)
May 17 Python
Keras 加载已经训练好的模型进行预测操作
Jun 17 Python
Python如何发送与接收大型数组
Aug 07 Python
Python 图片添加美颜效果
Apr 28 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
PDO的安全处理与事物处理方法
2016/10/31 PHP
PHP使用第三方即时获取物流动态实例详解
2017/04/27 PHP
phpstorm 正则匹配删除空行、注释行(替换注释行为空行)
2018/01/21 PHP
CI框架(CodeIgniter)实现的数据库增删改查操作总结
2018/05/23 PHP
在JavaScript中实现命名空间
2006/11/23 Javascript
jquery select选中的一个小问题
2009/10/11 Javascript
无阻塞加载脚本分析[全]
2011/01/20 Javascript
浅析JS中document对象的一些重要属性
2014/03/06 Javascript
Javascript核心读书有感之词法结构
2015/02/01 Javascript
jQuery实现图片预加载效果
2015/11/27 Javascript
javascript省市区三级联动下拉框菜单实例演示
2015/11/29 Javascript
jQuery根据表单name获取值的方法
2016/05/24 Javascript
jquery 追加元素append、prepend、before、after用法与区别分析
2016/12/02 Javascript
JS简单实现查看文档创建日期、修改日期和文档大小的方法示例
2018/04/08 Javascript
原生JS+HTML5实现的可调节写字板功能示例
2018/08/30 Javascript
微信小程序实现自动定位功能
2018/10/31 Javascript
Element-UI中Upload上传文件前端缓存处理示例
2019/02/21 Javascript
JavaScript图片旋转效果实现方法详解
2020/06/28 Javascript
Python的Django中将文件上传至七牛云存储的代码分享
2016/06/03 Python
python Matplotlib画图之调整字体大小的示例
2017/11/20 Python
详解python使用Nginx和uWSGI来运行Python应用
2018/01/09 Python
python 使用正则表达式按照多个空格分割字符的实例
2018/12/20 Python
python算法与数据结构之单链表的实现代码
2019/06/27 Python
python卸载后再次安装遇到的问题解决
2019/07/10 Python
python绘制雪景图
2019/12/16 Python
在服务器上安装python3.8.2环境的教程详解
2020/04/26 Python
25个CSS3动画按钮和菜单教程分享
2012/10/03 HTML / CSS
使用HTML和CSS实现的标签云效果(附demo)
2021/02/03 HTML / CSS
美国最大的骑马用品零售商:HorseLoverZ
2017/01/12 全球购物
ONLY瑞典官网:世界知名服装品牌
2018/06/19 全球购物
澳大利亚女士时装在线:Rockmans
2018/09/26 全球购物
广州某公司软件工程师面试题
2014/12/22 面试题
开业庆典邀请函
2014/01/08 职场文书
学生宿舍管理制度
2014/01/30 职场文书
房地产开盘策划方案
2014/02/10 职场文书
个人学习党的群众路线教育实践活动心得体会
2014/11/05 职场文书