第12章--继承的优缺点

第12章–继承的优缺点

本章探讨继承和子类化,重点是说明对 Python 而言尤为重要的两个细节:
• 子类化内置类型的缺点–例如写一个继承list的列表类
• 多重继承和方法解析顺序

子类化内置类型

结论:不要子类化内置类型,而是选择子类化collections模块对应的类比如UserDict UserList UserStr
原因:内置类型比如list、dict使用c语言编写的,内置类型不会调用用户定义的类覆盖的特殊方法
内置类型的子类覆盖的方法会不会隐式调用,CPython 没有制定官方规则。基本上,内置类型的方法不会调用子类覆盖的方法。例如,dict 的子类覆盖的
getitem() 方法不会被内置类型的 get() 方法调用。

具体代码对比

from collections import UserDict

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


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

ad=ADict(name='jason')
print(ad) #{'name': 'jason'}
ad['age']=64
print(ad)  # {'name': 'jason', 'age': [64, 64]}
ad.update(job='student')
print(ad) # {'name': 'jason', 'age': [64, 64], 'job': 'student'}

bd=BDict(name='jason')
print(bd) # {'name': ['jason', 'jason']}
bd['age']=64
print(bd) # {'name': ['jason', 'jason'], 'age': [64, 64]}
bd.update(job='student')
print(bd) # {'name': ['jason', 'jason'], 'age': [64, 64], 'job': ['student', 'student']}

ADict和BDict的setitem方法是一样的,把传进来的value设置成列表形式,ADict继承内置类型dict,BDict继承自UserDict,
ADict类型的init和update函数不会发现用户定义的setitem函数,而是继续用dict的setitem函数,导致了value的值的类型不一致,有的是非列表有的是列表,这不是用户愿意看到的
BDict类型的init和update函数都用到了用户定义的setitem函数,整个类实例的行为看上去都是一致的

多重继承和方法解析顺序

python支持多重继承
super()调用父类的方法会根据方法解析顺序(MRO)的顺序来调用方法
每个类都有一个内置属性__mro__,是一个元祖,会按照MRO列出各个父类,调用方式是CLassName.__mro__,而不是类的实例
如果想调用特定的父类的方法,可以通过ParentClass.fun(child_instance),把子类的实例传给父类的方法



class A():
    def fun(self):
        print("A fun of ",self)

class B(A):
    def fun(self):
        print("B fun of ",self)

class C(A):
    def fun(self):
        print("C fun of ",self)

class D(B,C):
    def fun(self):
        super().fun()

d=D()
d.fun() # B fun of  <__main__.D object at 0x00000286500AD438>
print("MRO of Class D ",D.__mro__)
# MRO of Class D  (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
C.fun(d) # C fun of  <__main__.D object at 0x0000020B7CA3D470>
A.fun(d) # A fun of  <__main__.D object at 0x000001FE08FED470>
发布了51 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36267931/article/details/103007432