美文网首页
Python基础33-面向对象(继承资源(属性与方法)的使用注意

Python基础33-面向对象(继承资源(属性与方法)的使用注意

作者: Jacob_LJ | 来源:发表于2018-06-04 23:28 被阅读11次

Python基础-面向对象

在Python中, 继承是指子类对父类资源的使用权

1 继承-属性与方法的使用权限

1.1 测试属性与方法分别如下

  • 公有属性/方法
  • 受保护属性/方法
  • 私有属性/方法
class Animal:
    a = 1 # 公有属性
    _b = 2 # 受保护属性
    __c = 3 # 私有属性

    #公有方法
    def t1(self):
        print("t1")

    # 受保护方法
    def _t2(self):
        print("t2")
    
    # 私有方法
    def __t3(self):
        print("t3")
    # 内置方法
    def __init__(self):
        print("init, Animal")


class Person(Animal):

    # 在实例对象(子类)内对以上属性及方法的访问权限
    def test(self):
        print(id(self.a)) # 打印地址的目的是为了证明子类对父类属性继承是`可以使用`,而非`拥有副本`
        print(self.a)
        print(self._b)
        # print(self.__c) # 不能访问私有属性

        self.t1()
        self._t2()
        # self.__t3() # 不能访问私有方法
        self.__init__() 

p = Person()
p.test()

print(id(Animal.a))
p.test()

>>>> 打印结果
init, Animal
4502964848
1
2
t1
t2
init, Animal
4502964848
4502964848
1
2
t1
t2
init, Animal

除私有的属性和私有的方法, 其他属性和方法子类基本都能继承(具有使用权)

2 继承-通过子类给父类属性进行赋值时,默认是指给之类增加一个与父类同名的属性

class Father:
    age = 10


class Son(Father):
    pass


print(Son.age) # 访问父类属性
Son.age = 9 # 给子类增加与父类同名属性

print(Son.age)

print(Father.age)
print(Son.__dict__)
print(Father.__dict__)

>>>>打印结果
10
9
10
{'__module__': '__main__', '__doc__': None, 'age': 9}
{'__module__': '__main__', 'age': 10, '__dict__': <attribute '__dict__' of 'Father' objects>, '__weakref__': <attribute '__weakref__' of 'Father' objects>, '__doc__': None}

3 继承的3种形态

继承的3种形态

4 几种形态应该遵循的标准原则

4.1 单继承

  • 遵循"从下到上的原则"
  • 自己身上没有这个资源, 就到父类里面去找,父类里面没有再往上找

4.2 无重叠的多继承

  • 遵循"单调原则"
  • 按照继承的先后顺序,优先调用左侧继承链上的资源

4.3 有重叠的多继承

  • 遵循"从下到上的原则"
  • 简单理解就是:
  1. A继承B继承C
  2. B重写了C类的方法, 那么A优先使用B类的方法

4 查看类的资源查找顺序方法

通过inspect模块进行

目的:假如继承链中多个父类重写的资源,要学会查找哪些类的重写资源会被优先调用

# 导入资源查看模块 inspect
import inspect


class D(object):
    pass

class B(D):
    pass


class C(D):
    pass

class A(B, C):
    pass

# 方法一
print(inspect.getmro(A))

# 方法二
print(A.__mro__)

# 方法三
print(A.mro())

>>>>打印结果

(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>]

TODO:《 针对于几种标准原则的方案演化》

  1. 不同 Python 版本 MRO 原则
  2. 菱形继承链问题

5 资源覆盖(MRO 优先级高的优先调用)

5.1 原理

  1. 基于MRO的资源检索链
  2. 优先级高的类具有一个与优先级低的类一样的一个资源(属性或方法)
  3. 会先选择优先级高的资源 ,而摒弃优先级低的资源(造成"覆盖"的假象)
class D(object):
    age = "d"
    pass

class C(D):
    age = "c"
    def test(self):
        print("c")
    pass

class B(D):
    # age = "b"
    def test(self):
        print("b")
    pass

class A(B, C):
    pass

a = A()
a.test()

print(A.mro())

print(A.age)
print(A().test())

>>>>打印结果
b
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>]
c
b
None

5.2 调用优先级高资源时,self 与 cls 的变化

结论:谁调用,就是谁

class D(object):
    pass

class C(D):
    def test(self):
        print(self)
    pass

class B(D):
    def test(self):
        print(self)

    @classmethod
    def test2(cls):
        print(cls)
    pass

class A(B, C):
    pass

A.test2()

a = A()
a.test()

>>>>打印结果

<class '__main__.A'>
<__main__.A object at 0x1011b79b0>

6 在低优先级类的方法中,通过"super"调用高优先级类的方法

  • Python3.x
class B:
    a = 1

    def __init__(self):
        self.b = 2
        self.xxx = "123"

    def t1(self):
        print("t1")

    @classmethod
    def t2(cls):
        print(cls)
        print("t2")

    @staticmethod
    def t3():
        print("t3")


class A(B):
    c = 3

    def __init__(self):
        super().__init__()
        self.e = "666"

    def tt1(self):
        print("tt1")

    @classmethod
    def tt2(cls):
        super().t2()
        print("tt2")

    @staticmethod
    def tt3():
        print("tt3")

    pass

a = A()
print(a.__dict__)

print("-" * 20)
A.tt2()

>>>>打印结果
{'b': 2, 'xxx': '123', 'e': '666'}
--------------------
<class '__main__.A'>
t2
tt2
  • Python2.2+
class B:
    a = 1

    def __init__(self):
        self.b = 2
        self.xxx = "123"

    def t1(self):
        print("t1")

    @classmethod
    def t2(cls):
        print(cls)
        print("t2")

    @staticmethod
    def t3():
        print("t3")


class A(B):
    c = 3

    def __init__(self):
        super(A, self).__init__()
        self.e = "666"

    def tt1(self):
        print("tt1")

    @classmethod
    def tt2(cls):
        super(A, cls).t2()
        print("tt2")

    @staticmethod
    def tt3():
        print("tt3")

    pass

a = A()
print(a.__dict__)

print("-" * 20)
A.tt2()

>>>>打印结果
{'b': 2, 'xxx': '123', 'e': '666'}
--------------------
<class '__main__.A'>
t2
tt2

注意

  1. super 和父类(超类)没有实质性的关联
    仅仅是沿着MRO链条, 找到下一级节点
  2. 保证调用形式的统一
    要是类名调用, 全是类名调用
    要是super调用, 全是super调用
    (混合使用容易出现死循环)

相关文章

  • Python基础33-面向对象(继承资源(属性与方法)的使用注意

    在Python中, 继承是指子类对父类资源的使用权 1 继承-属性与方法的使用权限 1.1 测试属性与方法分别如下...

  • 20170610基础知识-面向对象

    Object Oriented ProgrammingOOP:面向对象,使用对象、类、继承、封装、属性、方法、扩展...

  • python 10天快速教程 Day7

    本节重点 面向对象介绍 简单类与对象 魔法方法 继承、super 私有属性与私有方法 一、面向对象介绍 面向过程:...

  • 面向对象继承复习

    js基础的面向对象的继承 构造函数继承 这种方法的缺陷是只会继承构造函数上的实例属性,并不会继承原型对象上的属性,...

  • Python OOP-1

    0. OOP-Python面向对象 Python面向对象 面向对象编程基础公有私有继承组合,Mixin 魔法函数魔...

  • python的面向对象

    python的面向对象(ObjectOriented,OO)-面向对象编程-基础-公有私有-继承-组合,Minxi...

  • 面向对象的继承

    面向对象继承问题:属性继承:构造函数伪装方法继承:原型链 我们先写一个简单的对象 实现属性的继承 实现方法的继承 ...

  • JAVA基础——面向对象三大特性:封装、继承、多态

    JAVA基础——面向对象三大特性:封装、继承、多态 封装 封装就是使用特殊的语法,对成员属性和成员方法进行包装,达...

  • 2018-03-06

    基础篇: 面向对象的特征:继承+多态,封装。 继承的特性: 子类拥有父类非private的属性,方法。 子类可以拥...

  • python自定义功能之面向对象

    本章主要内容 类与对象 定义和使用类 类的属性和方法 类的继承 类的方法重载 总结: python中的类与对象与J...

网友评论

      本文标题:Python基础33-面向对象(继承资源(属性与方法)的使用注意

      本文链接:https://www.haomeiwen.com/subject/taaksftx.html