Python之类的属性查找

属性查找

单继承下的属性查找:

有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找……

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

Foo.f2():对象自己本身的__dict__里没有Foo.f2(),所以要去父类中找。但是传的参数中self为obj本身。所以再次运行self.f1()的时候其实是运行 obj.f1(),这时再去__dict__,找到执行Bar(Foo)中的f1。
如果就像让在调用Foo的f2时调用Foo的f1,则需要这样写:

class Foo:
     def __f1(self): # _Foo__f1
         print('Foo.f1')
     def f2(self):
         print('Foo.f2')
         # Foo.f1(self)
         self.__f1()

class Bar(Foo):
    def __f1(self): # _Bar__f1
        print('Bar.f1')

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

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

b=Bar()
b.f2()

b.f2()会在父类Foo中找到f2,先打印Foo.f2,然后执行到self.f1(),即b.f1(),仍会按照:对象本身->类Bar->父类Foo的顺序依次找下去,在类Bar中找到f1,因而打印结果为Foo.f1。

class A(object):
    def test(self):
        print('from A')


class B(A):
    def test(self):
        print('from B')


class C(A):
    def test(self):
        print('from C')


class D(B,C):
    pass


obj = D()
obj.test() # 结果为:from B

类以及该类的对象访问属性都是参照该类的mro列表

在Python3下:
D.mro() # 只要定义了类.mor()就会被定义出来;新式类内置了mro方法可以查看线性列表的内容,经典类没有该内置该方法
结果是: [<class ‘main.D’>, <class ‘main.B’>, <class ‘main.C’>, <class ‘main.A’>, <class ‘object’>]

python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

所以obj.test()的查找顺序是,先从对象obj本身的属性里找方法test,没有找到,则参照属性查找的发起者(即obj)所处类D的MRO列表来依次检索,首先在类D中未找到,然后再B中找到方法test

1.由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去,
2.由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去,

PS: super()函数,一旦被调用则是在mro()产生的列表里去找上一个,然后再进行.之后的调用。

总结:
类的相关属性的查找(类名.属性,该类的对象.属性),都是参照该类的mro

Python2和Python3都适用
PS:Python2和3在非菱形继承下查找顺序一样,新式类(即Python中默认继承object类)object类永远放最后一个查找;在Python2中非新式类就没有object在列表中。

菱形问题:

上面的图中,EFD最终继承一个非object类时出现的问题。

https://www.cnblogs.com/gandoufu/p/9634914.html

在这里插入图片描述
在这里插入图片描述

总结:

多继承要用,但是:
1、继承结构尽量不要过于复杂
2、要在多继承的背景下满足继承的什么“是”什么的关系 -> 推荐使用mixins原则

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值