9.继承、多继承、魔术方法

         继承         

 一、继承 问题引入

1.两个中有大量重复的代码, 是否能够只写一次 ?

抽象出一个更抽象的类,放公共代码

2.继承的意义是什么 ?

重用代码,方便代码的管理和修改

3.继承是复制变量空间嘛

只是引用,不会复制

二、分类关系图

三、从矩形类中派生正方形类

                                                     注:派生和继承是一个意思

class Rectangle(object):            #长方形类
    def __init__(self,length,width):
        self.length = length
        self.width = width

    def area(self):
        areas = self.length * self.width
        print(areas)

class Square(Rectangle):             #正方形类
    pass
a = Square(6,6)
a.area()

36

四、调用父类 重写方法

当子类重写父类方法之后,子类如果想再次调用父类的方法,可以使用这两种方法

                     方式一: 父类名.方法名(self)                                                         方式二: super.方法名()

注意:用类名调用的时候,( )里面要写self

class Rectangle(object):            #长方形类
    def __init__(self,length,width):
        self.length = length
        self.width = width

    def area(self):
        areas = self.length * self.width
        print(areas)

class Square(Rectangle):             #正方形类
    def __init__(self,length,width):
        if length == width:
            # self.length = length
            # self.width = width
            Rectangle.__init__(self, length, width)
            print('初始化成功')
        else:
            print('传入长宽不等,不进行初始化')

a = Square(6,6)
a.area()


初始化成功
36

五、顶级基类 object

class Rectangle:         #经典类
    pass
class Rectangle(object):        #新式类
    pass
#Python 2.x中默认都是经典类,只有显式继承了object才是新式类
#Python 3.x中默认都是新式类,写不写object都一样,都继承object
                        # __base__特殊属性
#__bass__:查看继承的父类                      #Rectangle.__base__
#__bases__:查看继承的全部父类                 #Rectangle.__bases__
class Rectangle(object):           
    def __init__(self,length,width):
        self.length = length
        self.width = width

    def area(self):
        areas = self.length * self.width
        print(areas)

class Square(Rectangle):
    pass

print(Square.__bases__ )
print(Square.__base__ )
a = Square(6,6)
a.area()

(<class '__main__.Rectangle'>,)
<class '__main__.Rectangle'>
36

       多继承       

一、多继承

 

通过C类实例的方法调用来看 当继承多个父类时,如果父类中有相同的方法, 那么子类会优先使用最先被继承的方法

 

 

class Base:
    pass
    def func(self):
        print('---------base---func---------')

class A(Base):
    pass
    def func_a(self):
        print('---------a---funca------------')
    def func(self):
            print('---------a---func---------')

class B(Base):
    pass
    def func_b(self):
        print('---------b---func_b------------')
    def func(self):
            print('---------b---func---------')

class D(Base):
    pass
    def func_d(self):
        print('---------D---func_d------------')
    def func(self):
            print('---------D---func---------')

class C(A,B,D):
    def func(self):
        print('---------c---func---------')
        super().func()

c = C()
c.func()

---------c---func---------
---------a---func---------

 

二、多继承 调用父类重写方法

当子类重写父类方法之后,子类如果想再次调用父类的方法,可以使用这两种方法

 

使用 super调用父类重名方法,可以通过类的__mro__属性来查看多继承的 情况下,子类调用父类方法时,在父类中的搜索顺序

 

li = C.mro()
for i in li:

    print(i)


<class '__main__.C'>
<class '__main__.A'>
<class '__main__.B'>
<class '__main__.D'>
<class '__main__.Base'>
<class 'object'>

在python3中,类被创建时会自动创建属性 __mro__ 解析顺序

类在生成时会自动生成方法解析顺序,可以通过 类名.mro()来查看

 

 

object是所有类的父类

三、基于多继承的 Mix-in 设计模式

 

     魔术方法     

__add__ :当类的实例之间使用+号时,会自动调用__add__这个魔法方法

一、魔术方法之运算方法

二、__str__ 和 __repr__

str和repr都是分别调用这两个魔术方法来实现的

调用str函数来处理实例对象,如果对象没有定义__str__方法,则调用__repr__方法。

调用repr函数来处理实例对象,则调用__repr__处理。

注:__str__和__repr__原理

在python中,__repr__和__str__这两个方法都是用于显示的,__str__是面向用户的,而 __repr__面向程序员。

使用内置函数str和repr方法在处理对象的时候,分别调用的是对象的__str__ 和__repr__方法

调用str函数来处理输出的对象,如果对象没有定义__str__方法,则调用__repr__方法 调用repr函数来处理输出的对象,则调用__repr__处理, 使用print操作 会首先尝试

调用__str__方法 ,如果__str__方法没有定义,则调用__repr__方法 在交互模式下,输入对象 显示对象 __repr__ 方法的返回值

 1.只写了__str__魔术方法: 交互模式输入:a ,返回的是一个对象 print(a) : 打印__str__魔术方法,返回的内容

 

2.只写了__repr__魔术方法:

交互模式输入 a :返回的是调用__repr__魔术方法,返回的内容

print(a) : 打印调用__repr__魔术方法,返回的内容

3.__repr__魔术方法 和 __str__魔术方法 都 写上

交互模式输入a :返回的是调用__repr__魔术方法,返回的内容

print(a) : 打印调用__str__魔术方法,返回的内容

__str__ 与 __repr__ 该如何抉择

str:

尽可能的提供简洁且有用的信息。 让用户尽可能吸收到必要的信息。

repr:

尽可能向开发者提供创建该对象时的必要信息。 让开发者可以直接通过复制粘贴来重建对象。

三、__call__方法

正常情况下,实例是不能像函数一样被调用的,要想实例能够被调用,就需要 定义 __call__ 方法

四、类中的一些查询相关信息的方法      (了解既可)

1、__class__ 查看类名 格式: 实例.__class__

2、__dict__ 查看全部属性,返回属性和属性值键值对形式 格式:实例.__dict__

3、__doc__ 查看对象文档,即类中(用三个引号引起来的部分) 格式:类名.__dict__

4、__bases__ 查看父类 格式:类名.__base__

5.__mro__ 查看多继承的情况下,子类调用父类方法时,搜索顺序 格式:子类名.__mro__ 实例.__class__.__mro__

 

posted @ 2018-07-11 15:48  浏阳河  阅读(226)  评论(0编辑  收藏  举报