20181214(继承,派生)

 

派生/继承/继承结构

派生描述了子类衍生出新的特性,新类保留已存类类型中所有需要的数据和行为,但允许修改或者其它的自定义操作,都不会修改原类的定义。 继承描述了子类属性从祖先类继承这样一种方式 继承结构表示多“代”派生,可以述成一个“族谱”,连续的子类,与祖先类都有关系。

 

一、继承

1、定义:继承是一种类与类之间的关系,是一种新建类的的方式,在python中支持一个儿子继承多个爹,即多继承。

新建的类称为子类或者派生类, 父类又可以称为基类或者超类。

子类会”遗传“父类的属性

 

2、使用继承的好处:减少代码冗余

3、使用继承的方法:

class Father:  # 定义一个父类
   pass
class FatherWang:  # 定义另一个父类
   pass

# 在子类中,类名后面括号内写上父类的名称即可
# 在python中,存在多个父类时,括号内用逗号隔开即可。其他语言不支持这个操作
class Son1(Father): # 单继承,基类是Father,派生类是Son1
   pass

class Son2(Father,FatherWang): #子类继承了两个父类
   pass

# 子类可以使用父类的属性和函数
# 如果子类中有,优先从子类中拿取,子类中没有,就从父类中拿取

class Parent:
   year = 2018
   def coding(self):
       print("coding...")

class Sub(Parent): # Parent的子类Sub
   year = 2019

print(Parent.year)  # 注意调取参数的语法
print(Sub.year)
s = Sub()  # 先从类中创建一个对象
print(s.year)  # 对象优先从其类中查找数据,没有的去父类中寻找
s.coding()
输出结果:
2018
2019
2019
coding...

 

4、查看继承

__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类.

交互模式下输入:

>>> class Father:pass
...
>>> class FatherWang:pass
...
>>> class Son(Father,FatherWang): pass
...
>>> Son.__bases__
(<class '__main__.Father'>, <class '__main__.FatherWang'>)
>>> Son.__base__
<class '__main__.Father'>

 

二、继承与抽象

通过继承,避免了重复代码的编写 #从父类中继承得到了一些基础属性 通过抽象,避免了继承到一些不该有的内容 #抽象即抽取类似部分或者比较像的部分。 应该先抽象再具体

(继承是拿到父类的属性,如果想要修改也可以自己修改;抽象就是尽可能求同,找出普适性的共同点,将其通过描述(定义变量或函数)确定下来(父类))

 

三、派生

派生:子类定义自己新的属性,如果与父类同名,以子类自己的为准。派生类是子类的一种,添加、修改了自己独有的属性的子类就是派生类。

 

在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要调用父类中重名的那个函数功能。此时用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值。

 

派生与覆盖:

子类出现与父类重复的名字 称之为覆盖 子类出现与父类不重复的名字 称之为派生

 

class Person:
   def __init__(self,name,age):
       self.name = name
       self.age = age

class Student(Person):  # 这是派生,有自己的内容
   def __init__(self,name,age,number):
       Person.__init__(self,name,age)  
       self.number = number
       
class Student1(Person):  # 这不是派生,因为没有自己的内容
pass
     

 

四、子类访问父类中的方法

两种方法,两种函数。

 

指名道姓调用函数:其实与继承没有什么关系。

 

super函数:super().__init__(name,age) 创建一个特殊的对象,用于调用父类的方法。

在python2 中,需要传入当前类和当前对象,super(Student,self).__init__(name,age,sex)

 

两种方法的区别:方式一其实和继承没有关系,方式二super()是依赖于继承的,即使没有继承关系,也会按照mro算法继续向后查找。

方法一:注意传参方式
class Person:
   def __init__(self,name,age):
       self.name = name
       self.age = age

class Student(Person):
   def __init__(self,name,age,number):
       Person.__init__(self,name,age)  # 直接调用Person中的函数
       self.number = number  # Person中没有的则需要子类自己处理



sut = Student("alex",33,110)
print(sut.__dict__)

方法二:注意传参方式
class Person:
   def __init__(self,name,age):
       self.name = name
       self.age = age

class Student(Person):
   def __init__(self,name,age,number):
       super().__init__(name,age)  # 此处传参没有self!
       self.number = number



sut = Student("alex",33,110)
print(sut.__dict__)

两种方法的区别:

#指名道姓
class A:
   def __init__(self):
       print('A的构造方法')
class B(A):
   def __init__(self):
       print('B的构造方法')
       A.__init__(self)
class C(A):
   def __init__(self):
       print('C的构造方法')
       A.__init__(self)
class D(B,C):
   def __init__(self):
       print('D的构造方法')
       B.__init__(self)
       C.__init__(self)
   pass

f1=D() #A.__init__被重复调用
'''
D的构造方法
B的构造方法
A的构造方法
C的构造方法
A的构造方法
'''


#使用super()
class A:
   def __init__(self):
       print('A的构造方法')
class B(A):
   def __init__(self):
       print('B的构造方法')
       super(B,self).__init__()
class C(A):
   def __init__(self):
       print('C的构造方法')
       super(C,self).__init__()
class D(B,C):
   def __init__(self):
       print('D的构造方法')
       super(D,self).__init__()

f1=D() #super()会基于mro列表查找,mro是一种算法,具体可以谷歌。
'''
D的构造方法
B的构造方法
C的构造方法
A的构造方法
'''

 

五、存在继承关系后的属性查找

先找对象,然后找类,然后找父类,然后是父类的父类(沿着继承关系)。。。直到报错

 

class Foo:
   def f1(self):
       print('Foo.f1')
   def f2(self):
       print('Foo.f2')
       self.f1()
class Bar(Foo):
   def f1(self):
      print('Bar.f1')

b=Bar()
b.f2()

输出结果:
Foo.f2
Bar.f1    #self为b,所以是b.f1(),Bar().f1()        

 

当存在多个父类时,按照继承顺序,从左到右,依次查找
class A:
   a=1
class B:
   a=2
class C(A,B):
   print(a)
输出结果为:
1

 

六、经典类与新式类

1.只有在python2中才分新式类和经典类,python3中统一都是新式类

2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类

3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类

4.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

object称之为根类 ,意为所有类都源自于object类。

 

七、菱形继承

存在共同父类时,在菱形继承中,会先深度再广度继承

如果在父类中,既有菱形又有非菱形,先按照继承顺序查找,碰到菱形时 就先广度再深度。

 

 

 

原文地址:https://www.cnblogs.com/realadmin/p/10121390.html