浅谈Python中的继承

继承

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 继承的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python基础类继承重写实现原理解析

    1.继承 继承是面向对象三大特性之一 - 通过继承我们可以使用一个类获取到其他类中的属性和方法 - 在定义类时,可以在类名后的括号中指定当前类的父类(超类.基类.super) - 子类(衍生类)可以直接继承父类中的所有的属性和方法 注意事项: a.在创建类时,如果省略了父类,则默认父类为object, object是所有类的父类,所有类都继承自object. b. isinstance()用来检查一个对象是否是一个类的实例 如果这个类是这个对象的父类,也会返回True 所有的对象都是object

  • Python class的继承方法代码实例

    这篇文章主要介绍了Python class的继承方法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 class parent(object): def implicit(self): print("Parent implicit()") def override(self): print("Parent override()") def altered(self): print("Parent a

  • Python多重继承之菱形继承的实例详解

    继承是面向对象编程的一个重要的方式,通过继承,子类就可以扩展父类的功能.在python中一个类能继承自不止一个父类,这叫做python的多重继承(Multiple Inheritance ). 语法 class SubclassName(BaseClass1, BaseClass2, BaseClass3, ...): pass 菱形继承 在多层继承和多继承同时使用的情况下,就会出现复杂的继承关系,多重多继承. 其中,就会出现菱形继承.如下图所示.mark 在这种结构中,在调用顺序上就出现了疑惑

  • Python 继承,重写,super()调用父类方法操作示例

    本文实例讲述了Python 继承,重写,super()调用父类方法操作.分享给大家供大家参考,具体如下: demo.py(继承,重写,super): # 父类 class Dog: def bark(self): print("汪汪叫") # 子类 继承 class XiaoTianQuan(Dog): def fly(self): print("我会飞") # 可以重写父类中的同名方法 def bark(self): # super().父类方法名 调用父类中的方

  • python继承threading.Thread实现有返回值的子类实例

    继承与threading.Thread实现有返回值的子类MyThread,废话不多说,大家直接看代码 import threading class MyThread(threading.Thread): def __init__(self,func,args=()): super(MyThread,self).__init__() self.func = func self.args = args def run(self): self.res = self.func(*self.args) d

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

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

  • Python 多线程其他属性以及继承Thread类详解

    一.线程常用属性 1.threading.currentThread:返回当前线程变量 2.threading.enumerate:返回一个包含正在运行的线程的list,正在运行的线程指的是线程启动后,结束前的状态 3.threading.activeCount:返回正在运行的线程数量,效果跟len(threading.enumer)一样 4.thr.setName:给线程设置名字 5.thr.getName:得到线程的名字. 举例: mport _thread as thread import

  • Python super()函数使用及多重继承

    super()函数可以用于继承父类的方法,语法如下: super(type[, object-or-type]) 虽然super()函数的使用比较简单,但是需要根据单继承和多继承来分析函数的调用关系. 首先,当类之间的继承关系为单继承时,函数调用关系也比较简单,可以参考如下的例子: #!/usr/bin/env python3 class A(object): def __init__(self): print('class A') class B(A): def __init__(self):

  • 浅谈Python中的继承

    继承 Python 中所有的类都是object类的子类,而object 继承自type 继承分为 接口继承和实现继承 接口继承:使用父类的接口名,子类重写这个方法.尽可能的继承接口类,在子类中实现方法,鼓励对接口类的多继承,这样遵循接口隔离原则,有利于归一化设计,不提倡对抽象类进行多继承 实现继承:子类不需要实现任何东西,直接使用父类接口和实现会增强代码的耦合性,不推荐使用. 一些细节 类继承最终要被实例化,我们多数时候使用的还是对象而不是类.因此我们还是来一点点看继- 继承的过程 承仅仅是一种

  • 浅谈python中的面向对象和类的基本语法

    当我发现要写python的面向对象的时候,我是踌躇满面,坐立不安呀.我一直在想:这个坑应该怎么爬?因为python中关于面向对象的内容很多,如果要讲透,最好是用面向对象的思想重新学一遍前面的内容.这个坑是如此之大,犹豫再三,还是只捡一下重要的内容来讲吧,不足的内容只能靠大家自己去补充了. 惯例声明一下,我使用的版本是 python2.7,版本之间可能存在差异. 好,在开讲之前,我们先思考一个问题,看代码: 为什么我只创建是为 a 赋值,就可以使用一些我没写过的方法? 可能会有小伙伴说:因为 a

  • 浅谈Python中带_的变量或函数命名

    Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下,不同程序员编写的 Python 代码可以保持最大程度的相似风格.这样就易于阅读,易于在程序员之间交流. python中的标识符可以包含数字.字母和_,但必须以字母或者_开头,其中以_开头的命名一般具有特殊的意义. 前后均带有双下划线__的命名 一般用于特殊方法的命名,用来实现对象的一些行为或者功能,比如__new__()方法用来创建实例,__init__()方法用来初始化对象,

  • 浅谈Python中range与Numpy中arange的比较

    本文先比较range与arange的异同点,再详细介绍各自的用法,然后列举了几个简单的示例,最后对xrange进行了简单的说明. 1. range与arange的比较 (1)相同点:A.参数的可选性.默认缺省值是一样的:B.结果均包括开始值,不包括结束值: C.arange的参数为整数是,与range函数等价:D.都具备索引查找.要素截取等操作. (2)不同点:A.range函数的参数只能为整数,arange的参数为数值型,包括整数和浮点数: B.输出的数据类型不同,range的输出为列表(li

  • 浅谈python中的多态

    一.多态 多态是指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等.(一个抽象类有多个子类,因而多态的概念依赖于继承) import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class Cat(Animal): #动物的形态之一:猫 def talk(self): print('say miaomiao') class Dog(Animal): #动

  • 浅谈Python中对象是如何被调用的

    目录 楔子 从 Python 的角度看对象的调用 从解释器的角度看对象的调用 小结 楔子 我们知道对象是如何被创建的,主要有两种方式,一种是通过Python/C API,另一种是通过调用类型对象.对于内置类型的实例对象而言,这两种方式都是支持的,比如列表,我们即可以通过[]创建,也可以通过list(),前者是Python/C API,后者是调用类型对象. 但对于自定义类的实例对象而言,我们只能通过调用类型对象的方式来创建.而一个对象如果可以被调用,那么这个对象就是callable,否则就不是ca

  • 浅谈python中copy和deepcopy中的区别

    在下是个编程爱好者,最近将魔爪伸向了Python编程.....遇到copy和deepcopy感到很困惑,现在针对这两个方法进行区分,一种是浅复制(copy),一种是深度复制(deepcopy). 首先说一下deepcopy,所谓的深度复制,在这里我理解的是完全复制然后变成一个新的对象,复制的对象和被复制的对象没有任何关系,彼此之间无论怎么改变都相互不影响. 然后说一下copy,在这里我分为两类来说,一种是字典数据类型的copy函数,一种是copy包的copy函数. 一.字典数据类型的copy函数

  • 浅谈python中列表、字符串、字典的常用操作

    列表操作如此下: a = ["haha","xixi","baba"] 增:a.append[gg] a.insert[1,gg] 在下标为1的地方,新增 gg 删:a.remove(haha) 删除列表中从左往右,第一个匹配到的 haha del a.[0] 删除下标为0 对应的值 a.pop(0) 括号里不写内容,默认删除最后一个,写了,就删除对应下标的内容 改:a.[0] = "gg" 查:a[0] a.index(&q

  • 浅谈Python中函数的参数传递

    1.普通的参数传递 >>> def add(a,b): return a+b >>> print add(1,2) 3 >>> print add('abc','123') abc123 2.参数个数可选,参数有默认值的传递 >>> def myjoin(string,sep='_'): return sep.join(string) >>> myjoin('Test') 'T_e_s_t' >>>

  • 浅谈python中的getattr函数 hasattr函数

    hasattr(object, name) 作用:判断对象object是否包含名为name的特性(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的). 示例: >>> hasattr(list, 'append') True >>> hasattr(list, 'add') False getattr(object,name,default): 作用:返回object的名称为name的属性的属性值,如果属性name存在,则直接返回其

随机推荐