详细总结Python类的多继承知识

一、Python不同版本的类

  • Python2.2之前是没有共同的祖先的,之后引入Object类,它是所有类的共同祖先类Object
  • Python2中为了兼容,分为古典类(旧式类)和新式类
  • Python3中全部都是新式类
  • 新式类都是继承自Object的,新式类可以使用super
#古典类在python2.x中运行
class A: pass

print(dir(A))            #    ['__doc__', '__module__']
print(A.__bases__)        #    ()
a = A()
print(a.__class__)        #     __main__.A
print(type(a))            #    <type 'instance'>

新式类

#新式类在python3.x中运行
class B: pass

print(dir(B))   #   ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
print(B.__bases__)  #   (<class 'object'>,)
B = B()
print(B.__class__)  #   <class '__main__.B'>
print(type(B))      #   <class '__main__.B'>

二、多继承

OCP原则:多用”继承“,少修改

继承的用途:增强基类,实现多态

多态

  • 在面向对象中,父类、子类通过继承联系在一起,如果可以通过一套方法,就可以实现不同变现,就是多态
  • 一个类继承自多个类就是多继承它将具有多个类的特征

三、多继承弊端

多继承很好的模拟了世界,因为事务很少单一继承,但是舍弃简单,必然引入复杂性,带来了冲突

如同一个孩子继承了来自父母双方的特征,那么到底眼睛像爸爸还是妈妈尼?孩子究竟改像谁多一点尼?

多继承的实现会导致编译器设计的复杂度增加,所以现在很多语言舍弃了类的多继承

C++支持多继承;Java舍弃了多继承

  • Java中,一个类可以实现多个接口,一个接口也可以继承多个接口。Java的接口很纯粹,只是方法声明,继承者必须实现这些方法,就具有了这些能力,就能干什么

多继承可能会带来二义性,例如,猫和狗都继承自动物类,现在一个类多继承了猫和狗类,猫和狗都有了shout方法,子类究竟继承谁的shout尼?

  • 解决方案:实现了多继承的语言,要解决二义性,深度优先或者广度优先

四、Python多继承实现

class ClassName(基类列表):
    类体

多继承带来的路径选择问题,究竟继承那个父类的特征尼?

  • 究竟先广度优先,还是深度优先

Python使用MRO(method resolution order) 解决类搜索顺序问题。

  • 经典算法,按照定义从左到右,深度优先策略【比如Python2.2之前,左图的MRO算法,MyClass→D→B→A→C→A】
  • 新式类算法,经典算法的升级,重复的只保留最后一个。【左图MRO是:MyClass→D→B→C→A→object】
  • C3算法,在类被创建出来的时候,就计算除一个MRO有序列表。【Python3唯一支持的算法,左图中MRO是MyClass→D→B→C→A→object】C3过于复杂,没必要去记,我们只要记住【object.mro(),显示继承的方法,从左到右依次查找】

五、多继承的缺点

当类很多,继承复杂的情况下,继承路径太多,很难说清什么样的继承路径

团队协作开发,如果引入多继承,那代码将不可控

不管编程语言是否支持多继承,都应当避免多继承

Pythond的面向对象,我们看到太灵活,太开放,所以要团队守规矩

六、Mixin

类有下面的继承关系

文档Document类是其他所有文档类的抽象基类,Word、Pdf类是Document的子类

需求:为Document子类提供打印能力思路:

1、在Document中提供print方法

class Document:

    def __init__(self,content):
        self.coutent = content

    def print(self):
        print(self.coutent)

class Word(Document): pass

class Pdf(Document):  pass

a = Word("tom com")
a.print()   #   tom com

基类提供的方法不因该具体实现,因为它未必适合子类的打印,子类中需要覆盖重写。

print算是一种能力 -- 打印功能,不是所有的Document的子类都需要的,所以,从这个角度出发有点问题

class Document:

    def __init__(self,content):
        self.coutent = content

    def print(self):
        print(self.coutent)

class Word(Document):
    def print(self):
        print("Word print {}".format(self.coutent))

class Pdf(Document):  pass

a = Word("tom com")
a.print()   #   Word print tom com

思路二:需要打印的子类上增加

如果现有子类上直接增加,违反了OCP的原则,所以应该继承后增加

class Document:        # 不允许修改
    def __init__(self,content):
        self.coutent = content

    def print(self):
        print(self.coutent)

class Word(Document): pass    # 不允许修改

class Pdf(Document):  pass    #    不允许修改

class PrinttableWord(Word):
    def print(self):
        print("PrinttableWord print {}".format(self.coutent))

print(PrinttableWord.mro()) #   [<class '__main__.PrinttableWord'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
a = PrinttableWord("tom com")
a.print()   #   PrinttableWord print tom com

看似不错,如果还要提供其他类似能力,如何继承?

应用于网络,文档应该具备序列化的能力,类上就应该实现序列化可序列化还可能分为使用pickle、josn、messagepack等

这个时候,发现,类又可能太多了,继承的方式不是很好了

功能太多,A类需要某几样功能,B类需要另外几样功能,很繁琐

思路三:装饰器,用装饰器增强一个类,把功能给类附加上去,那个类需要,就装饰它

def printable(cls):
    def _print(self):
        print("_print 装饰器 {}".format(self.coutent))
        return _print
    cls.print = _print
    return cls

class Document:
    def __init__(self,content):
        self.coutent = content

    def print(self):
        print(self.coutent)

class Word(Document): pass

class Pdf(Document):  pass

@printable
class PrinttableWord(Word): pass    #先继承,后装饰

print(PrinttableWord.__dict__)  #   {'__module__': '__main__', '__doc__': None, 'print': <function printable.<locals>._print at 0x0173C228>}
a = PrinttableWord("tom")
a.print()   #   _print 装饰器 tom

优点:简单方便,在需要的地方动态增加

思路四:Mixin  【用类去继承】

先看代码

class PrintableMixin:
    def print(self):
        print("PrintableMixin {}".format(self.coutent))

class Document:
    def __init__(self,content):
        self.coutent = content

    def print(self):
        print(self.coutent)

class Word(Document): pass

class Pdf(Document):  pass

class PrinttableWord(PrintableMixin,Word): pass    

print(PrinttableWord.mro())     #   [<class '__main__.PrinttableWord'>, <class '__main__.PrintableMixin'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
print(PrinttableWord.__dict__)  #   {'__module__': '__main__', '__doc__': None}
a = PrinttableWord("tom")
a.print()   #   PrintableMixin tom

Mixin就是其他类混合进来,同时带来了类的属性和方法

这里看来Mixin类和装饰器效果一样,也什么特别的,但是Mixin是类,就可以继承,增强功能

class PrintableMixin:
    def print(self):
        print("PrintableMixin {}".format(self.coutent))

class Document:
    def __init__(self,content):
        self.coutent = content

    def print(self):
        print(self.coutent)

class Word(Document): pass

class Pdf(Document):  pass

class PrinttableWord(PrintableMixin,Word): pass

class SuperPrintableMixin(PrintableMixin,Word):
    def print(self):
        print("~"*30)
        super(SuperPrintableMixin, self).print()
        print("~"*30)

print(SuperPrintableMixin.mro())     #  [<class '__main__.SuperPrintableMixin'>, <class '__main__.PrintableMixin'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
print(SuperPrintableMixin.__dict__)  #  {'__module__': '__main__', 'print': <function SuperPrintableMixin.print at 0x018264B0>, '__doc__': None}
a = SuperPrintableMixin("tom")
a.print()   #   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            #   PrintableMixin tom
            #   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

七、Mixin类

Minxin本质上就是多继承实现的

Mixin体现的是一种组合的设计模式

在面向对象的设计中,一个负载的类,往往需要很多功能,而这些功能有来自不同的类提供,这就需要很多的类组合在一起

从设计模式的角度来说,多组合,少继承。

  • Mixin类的使用原则
  • Mixin类中不应该显示的出现__init__初始化方法
  • Mixin类通常不能独立工作,因为它是准备混入别的类中的部分功能实现
  • Mixin类的祖先类也应该是Mixin类
  • 使用时,Mixin类通常在继承列表第一个位置,例如:class PrintableWord(PrintableMixin,Word):pass

到此这篇关于总结Python类的多继承知识的文章就介绍到这了,更多相关Python类的多继承内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python中的单继承与多继承实例分析

    本文实例讲述了Python中的单继承与多继承.分享给大家供大家参考,具体如下: 单继承 一.介绍 Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义.派生类的定义如下所示: class DerivedClassName(BaseClassName1): <statement-1> . . . <statement-N> 需要注意圆括号中基类的顺序,若是基类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找基类

  • Python面向对象程序设计多继承和多态用法示例

    本文实例讲述了Python面向对象程序设计多继承和多态用法.分享给大家供大家参考,具体如下: 多继承 就是一个子类继承多个父类: 多继承的例子,如下: # -*- coding:utf-8 -*- #! python3 class Base(object): def test(self): print("------base") class A(Base): def test1(self): print("-----test1") class B(Base): de

  • 在python里面运用多继承方法详解

    如何在PYTHON里面运用多继承 class Father: def hobby(self): print("love to play video game.") class Mother: def cook(self): print("love to cook anything.") #比如说有两个类,如果想要一个子类同时继承这两个类,应该怎么操作呢. class Father: def hobby(self): print("love to play

  • Python面向对象程序设计之继承与多继承用法分析

    本文实例讲述了Python面向对象程序设计之继承与多继承.分享给大家供大家参考,具体如下: 1. 继承 在C++和Java中,使用继承时,子类的构造函数会自动调用父类的构造函数,但在Python中,子类必须显式的在__init__()函数中再次调用父类中的__init__()函数.如下例: class Employee(object): def __init__(self, name, salary = 0): self.name = name self.salary = salary def

  • Python多继承顺序实例分析

    本文实例讲述了Python多继承顺序.分享给大家供大家参考,具体如下: 示例1: #-*- coding:utf-8 -*- #!python2 class A(object): def caller(self): print 'A caller' self.called() def called(self): print 'A called' class B(object): def called(self): print 'B called' class C(B,A): pass if __

  • Python多继承原理与用法示例

    本文实例讲述了Python多继承原理与用法.分享给大家供大家参考,具体如下: python中使用多继承,会涉及到查找顺序(MRO).重复调用(钻石继承,也叫菱形继承问题)等 MRO MRO即method resolution order,用于判断子类调用的属性来自于哪个父类.在Python2.3之前,MRO是基于深度优先算法的,自2.3开始使用C3算法,定义类时需要继承object,这样的类称为新式类,否则为旧式类 从图中可以看出,旧式类查找属性时是深度优先搜索,新式类则是广度优先搜索 C3算法

  • python支持多继承吗

    大部分面向对象的编程语言(除了C++)都只支持单继承,而不支持多继承,为什么呢?因为多继承不仅增加编程复杂度,而且容易导致莫名其妙的错误. Python虽然语法上支持多继承,但是却不推荐使用多继承,而是推荐使用单继承,这样可以保证编程思路更清晰,也可以避免不必要的麻烦. 当以一个子类有多个直接父类时,该子类会继承得到所有父类的方法,但是如果其中有多个父类包含同名方法会发生什么?此时排在前面的父类中的方法会"遮蔽"后面父类中的方法. 栗子如下: #coding=utf-8 class I

  • python多继承(钻石继承)问题和解决方法简单示例

    本文实例讲述了python多继承(钻石继承)问题和解决方法.分享给大家供大家参考,具体如下: 在菱形多继承中,如果用父类.__init__()来调用父类的初始化方法,最上层会执行两次,所以遇到这种情况,python中用super.__init__()来解决这个问题. # -*- coding:utf-8 -*- #! python3 class Grand_father(object): def __init__(self): print('爷爷') class Father_left(Gran

  • Python多继承以及MRO顺序的使用

    多继承以及MRO顺序 1. 单独调用父类的方法 # coding=utf-8 print("******多继承使用类名.__init__ 发生的状态******") class Parent(object): def __init__(self, name): print('parent的init开始被调用') self.name = name print('parent的init结束被调用') class Son1(Parent): def __init__(self, name,

  • 详细总结Python类的多继承知识

    一.Python不同版本的类 Python2.2之前是没有共同的祖先的,之后引入Object类,它是所有类的共同祖先类Object Python2中为了兼容,分为古典类(旧式类)和新式类 Python3中全部都是新式类 新式类都是继承自Object的,新式类可以使用super #古典类在python2.x中运行 class A: pass print(dir(A)) # ['__doc__', '__module__'] print(A.__bases__) # () a = A() print

  • 浅谈Python类的单继承相关知识

    一.类的继承 面向对象三要素之一,继承Inheritance 人类和猫类都继承自动物类. 个体继承自父母,继承了父母的一部分特征,但也可以有自己的个性. 在面向对象的世界中,从父类继承,就可以直接拥有父类的属性和方法,这样就可以减少代码.多服用.子类可以定义自己的属性和方法 class Animal: def __init__(self,name): self._name = name def shout(self): print("{} shouts".format(self.__c

  • 详细介绍python类及类的用法

    一.类的成员 类的成员包括:属性和方法. 属性可以分为:静态属性和实例属性 方法可以分为:普通方法.类方法和静态方法. 1.1 类的属性 属性可以分为:静态属性和实例属性. 实例属性属于对象,而静态属性属于类. 通过类创建对象时,如果每个对象都具有相同的属性,那么就使用静态属性. 1.1.1 静态属性的创建方式 静态属性是属于类的,所以不用创建对象访问. class Province: # 静态字段 country = '中国' # 直接访问静态字段 Province.country 例如: 1

  • Python类的定义继承调用比较方法技巧

    目录 一.类的约束 二.类的定义 2.1.创建创建 2.1.1.类的导入 2.1.2.构造器 2.1.3.类属性 三.类的继承 3.1.单继承 3.2.多继承 3.3.调用父类方法 3.4.属性扩展 3.4.1.完全扩展 3.4.2.单独扩展 四.类的调用 五.抽象类 5.1.强制类型检查 六.类的比较 一.类的约束 # _开头: 私有变量: # __开问: 私有变量,不能被继承: # __xxx__: 能被访问,不能被继承: class A: def __init__(self): self.

  • Python类的基础入门知识

    复制代码 代码如下: class Account(object): "一个简单的类" account_type="Basic" def __init__(self,name,balance): "初始化一个新的Account实例" self.name=name self.balance=balance def deposit(self,amt): "存款" self.balance=self.balance+amt def w

  • 详解Python类和对象内容

    目录 一.什么是Python类? 二.Python类中的方法和属性 2.1.Python类中的方法 2.2.Python类中的属性 三.面向对象的概念 3.1.Python类:继承 3.2.Python类:多态性 3.3.Python类:抽象 一.什么是Python类? python中的类是创建特定对象的蓝图.它使您可以以特定方式构建软件.问题来了,怎么办?类允许我们以一种易于重用的方式对我们的数据和函数进行逻辑分组,并在需要时进行构建.考虑下图. 在第一张图片(A)中,它代表了一个可以被视为C

  • Python类的继承与多态详细介绍

    目录 概念 类的创建 类的继承 多态的使用 概念 类(Class): 用来描述具有相同的属性和方法的对象的集合. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中且在函数体之外.类变量通常不作为实例变量使用. 类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用 self:self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类. 类调用 Car.weight 实例化  car01=Car(5) 实例对象调用  car01

  • python 类的继承 实例方法.静态方法.类方法的代码解析

    这篇文章主要介绍了python 类的继承 实例方法.静态方法.类方法的代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 dt={} class Denglu: def register(self,name,psd): if name.isalnum() and psd.isalnum(): if name not in dt.keys(): dt[name]=psd print('注册成功') else: print('已经存在该用户名'

  • Python类继承和多态原理解析

    这篇文章主要介绍了python类继承和多态原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 现在属于是老年人的脑子,东西写着写着就忘了,东西记着记着就不知道了.之前学C++的时候就把类.对象这块弄得乱七八糟,现在是因为很想玩python,所以就看看python的类和对象. 就像说的,类有三个特征:封装.继承.多态. 1.封装:类封装了一些方法,可通过一定的规则约定方法进行访问权限. C++中的成员变量有public.private.pto

  • 一篇文章带你搞懂Python类的相关知识

    一.什么是类 类(class),作为代码的父亲,可以说它包裹了很多有趣的函数和方法以及变量,下面我们试着简单创建一个吧. 这样就算创建了我们的第一个类了.大家可以看到这里面有一个self,其实它指的就是类aa的实例.每个类中的函数只要你不是类函数或者静态函数你都得加上这个self,当然你也可以用其他的代替这个self,只不过这是python中的写法,就好比Java 中的this. 二.类的方法 1.静态方法,类方法,普通方法 类一般常用有三种方法,即为static method(静态方法),cl

随机推荐