python新式类c3算法_Python新式类继承的C3算法

在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果。

可以通过代码来验证下:

classNewStyleClassA(object):

var= 'New Style Class A'

classNewStyleClassB(NewStyleClassA):pass

classNewStyleClassC(NewStyleClassA):

var= 'New Style Class C'

classSubNewStyleClass(NewStyleClassB, NewStyleClassC):pass

if __name__ == '__main__':print(SubNewStyleClass.mro())print(SubNewStyleClass.var)

从第一段代码的运行结果来看,与广度优先的算法结果恰巧相同,但也只是恰巧相同,不等于就是广度优先的算法。

[, , , , ]

New Style Class C

通过对代码进行修改可以证实:

将NewStyleClassC改为继承自object

classNewStyleClassA(object):

var= 'New Style Class A'

classNewStyleClassB(NewStyleClassA):pass

classNewStyleClassC(object):

var= 'New Style Class C'

classSubNewStyleClass(NewStyleClassB, NewStyleClassC):pass

if __name__ == '__main__':print(SubNewStyleClass.mro())print(SubNewStyleClass.var)

运行代码输出结果

[, , , , ]

New Style Class A

从代码运行结果上看,并不符合广度优先的原则。

关于C3算法,在Python官方文档中是如此解释的:

take the head of the first list, i.e L[B1][0]; if this head is not in the tail of any of the other lists, then add it to the linearization of C and remove it from the lists in the merge, otherwise look at the head of the next list and take it, if it is a good head. Then repeat the operation until all the class are removed or it is impossible to find good heads. In this case, it is impossible to construct the merge, Python 2.3 will refuse to create the class C and will raise an exception.

C3算法的本质就是Merge,不断地把mro()函数返回的序列进行Merge,规则如下:

1. 如果第一个序列的第一个元素,是后续序列的第一个元素,或者不再后续序列中再次出现,则将这个元素合并到最终的方法解析顺序序列中,并从当前操作的全部序列中删除。

2. 如果不符合,则跳过此元素,查找下一个列表的第一个元素,重复1的判断规则

使用第一段代码逐步进行方法解析:

1.先打印NewStyleClassB和NewStyleClassC的mro(),得到他们的继承顺序序列

[, , ]

[, ]

2.根据C3算法逐步对继承顺序进行解析:

mro(SubNewStyleClass)= [SubNewStyleClass] +merge(mro(NewStyleClassB), mro(NewStyleClassC), [NewStyleClassB, NewStyleClassC])#根据第一步的打印结果,可以得出

= [SubNewStyleClass] +merge([NewStyleClassB, NewStyleClassA, object], [NewStyleClassC, NewStyleClassA, object], [NewStyleClassB, NewStyleClassC])#判断merge的当前序列第一个元素 NewStyleClassB, 在第三个序列中的第一个元素也存在,所以将其合并到最终序列并且删除:

= [SubNewStyleClass, NewStyleClassB] +merge([NewStyleClassA, object], [NewStyleClassC, NewStyleClassA, object], [NewStyleClassC])#判断merge的当前序列第一个元素 NewStyleClassA,在第二个序列中存在,并且不为第二个序列的第一个元素,则跳过

#继续判断第二个序列中的第一个元素 NewStyleClassC,在第三个序列中存在,并且为第一个元素,所以将其合并到最终序列并且删除:

= [SubNewStyleClass, NewStyleClassB, NewStyleClassC] +merge([NewStyleClassA, object], [NewStyleClassA, object])#目前第一个序列的第一个元素是NewStyleClassA,所以再次对NewStyleClassA进行判断。

#NewStyleClassA在第二个序列中存在,并且为第二个序列的第一个元素,所以将其合并到最终序列并且删除:

= [SubNewStyleClass, NewStyleClassB, NewStyleClassC, NewStyleClassA] +merge([object], [object])#最终object,在第二个序列中出现,并且为第一个元素,所以将其合并到最终的序列并且删除,得到最终的继承顺序:

= [SubNewStyleClass, NewStyleClassB, NewStyleClassC, NewStyleClassA, object)

解析的结果和调用SubNewStyleClass.mro()方法打印出的结果是相同的:

[, , , , ]

使用第二段代码逐步进行方法解析:

1. 先打印NewStyleClassB和NewStyleClassC的mro(),得到他们的继承顺序序列

[, , ]

[, ]

2. 根据C3算法逐步对继承顺序进行解析:

mro(SubNewStyleClass)= [SubNewStyleClass] +merge(mro(NewStyleClassB), mro(NewStyleClassC), [NewStyleClassB, NewStyleClassC])#根据第一步的打印结果,可以得出

= [SubNewStyleClass] +merge([NewStyleClassB, NewStyleClassA, object], [NewStyleClassC, object], [NewStyleClassB, NewStyleClassC])#判断merge的当前序列第一个元素 NewStyleClassB, 在第三个序列中的第一个元素也存在,所以将其合并到最终序列并且删除:

= [SubNewStyleClass, NewStyleClassB] +merge([NewStyleClassA, object], [NewStyleClassC, object], [NewStyleClassC])#判断merge的当前序列第一个元素 NewStyleClassA,在后续的序列中都不存在,所以将其合并到最终的序列并且删除:

= [SubNewStyleClass, NewStyleClassB, NewStyleClassA] +merge([object], [NewStyleClassC, object], [NewStyleClassC])#判断merge的当前序列第一个元素 object,在第二个序列中出现,并且不是第一个元素,则跳过

#跳过object后,继续判断下个序列的第一个元素,也就是第二个序列的第一个元素NewStyleClassC,在第三个序列中出现并且为第一个元素,所以将其合并到最终的序列并且删除:

= [SubNewStyleClass, NewStyleClassB, NewStyleClassA, NewStyleClassC] +merge([object], [object])#再次判断object,在第二个序列中出现,并且为第一个元素,所以将其合并到最终的序列并且删除,得到最终的继承顺序:

= [SubNewStyleClass, NewStyleClassB, NewStyleClassA, NewStyleClassC, object)

和调用SubNewStyleClass.mro()方法打印出的结果是相同的

[, , , , ]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值