Python继承的优缺点

本文探讨了Python继承的优缺点,包括子类化内置类型的问题,多重继承和方法解析顺序(MRO),以及多重继承的应用和建议。强调了直接子类化内置类型的风险,推荐使用collections模块的类进行扩展,并解释了MRO如何解决菱形问题。最后提出了8点关于多重继承的指导原则,如区分接口和实现继承,使用抽象基类作为接口,以及优先考虑对象组合。
摘要由CSDN通过智能技术生成

推出继承的初衷是让新手顺利使用只有专家才能设计出来的框架!

子类化内置类型的问题

在Python2.2之前,内置类型不能子类化,如list、dict等。

在Python2.2之后,内置类型可以子类化了,但是要注意的是:内置类型(使用C语言编写)不会调用用户定义的类覆盖特殊方法。

至于内置类型的子类覆盖覆盖的方法会不会隐式调用,CPython没有制定官方规则。基本上,内置类型的方法不会调用子类覆盖的方法。

例如,dict的子类覆盖了__getitem__()方法 但不会被内置类型的get()方法调用,只能应用在[]运算符 dict[key]形式中。(感觉这也是理所当然)

示例,dict的__init__和__upate__方法会忽略掉子类覆盖的__setitem__方法

class DoubleDict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(key, [value] * 2)


dd = DoubleDict(one=1)
print(dd)

dd['two'] = 2
print(dd)

dd.update(three=3)
print(dd)
打印
{'one': 1}
{'one': 1, 'two': [2, 2]}
{'one': 1, 'two': [2, 2], 'three': 3}

知识点:

  1. 字典的init和update方法,都可以使用key=value的形式传入

  1. __setitem__方法,没有影响到init和update方法的功能

  1. super().__setitem__可以委托给超类处理,这里不需要传入self了

原生类型这种行为违背了面向对象编程的一个基本原则:始终应该从实例(self)所属的类开始搜索方法,即使在超类实现的类中调用也是如此。在上面的糟糕的局面中,__missing__方法却能按照预期工作,不过这这是个例。

不过只有实例内部的调用有这个问题,内置类型的方法调用其他类的方法,如果被覆盖了,也不会被调用。

ps:self.get()不会调用self.__getitem__()

示例,dict.update方法会忽略AnswerDict.__getitem__方法

class AnswerDict(dict):
    def __getitem__(self, item):
        return 42


ad = AnswerDict(a=1)
print(ad['a'])

d = {}
d.update(ad)
print(d['a'])

以上可以看到,dict.update方法忽略了AnswerDict.__getitem__()

综上所述:

直接子类化内置类型(list、dict、str等)容易出错,因为内置类型的方法通常会忽略用户覆盖的方法。

不要子类化内置类型,应该继承collection模块中的类,如UserDict、UserList、UserString,这写类都做了特殊设计,因此易于扩展

示例,改为继承UserDict类,上面出现的问题都解决了

import collections


class DoubleDict(coll
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值