python之面向对象编程(五)多继承与super函数

多继承

python支持多继承,使用多继承可以大大减少重复代码。

多继承涉及到最重要的知识点是变量搜索顺序,首先搜索的是实例的命名空间,其次搜索本类的命名空间,再次是搜索父类的命名空间。多个父类搜索的顺序比较复杂,具体可以使用“类名.mro()”函数打印查看。

多继承的搜索顺序涉及到C3算法,有兴趣的可以看我前几天发布的文章——“python之多继承广度优先C3算法原理通俗易懂的讲解”,在这里有详细讲解。

案例如下:

class A:
    def func(self):
        print('A')


class B:
    def func(self):
        print('B')


class C(A, B):
    def func(self):
        print('C')


print(C.mro())


out:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

super函数

super函数是用来在子类中调用父类的资源。注意在python3中super()函数可以不加参数,它有2个默认值,默认值1是本类,默认值2是self。在python2中需要写明参数,即super(类名,self)。

class A:
    def func(self):
        print('A')


class B:
    def func(self):
        print('B')


class C(A, B):
    def func(self):
        print('C')
        super().func()


cc = C()
cc.func()

out:
C
A

假设在上述案例中不是使用A类的方法而是要使用B类中的func,此时就不能使用super(),应该使用“类名.方法名(self)”。案例如下:

class C(A, B):
    def func(self):
        print('C')
        super().func()
        B.func(self)


cc = C()
cc.func()

out:
C
A
B

请注意以下2行代码的区别:

class C(A, B):
    def func(self):
        print('C')
        super().func()
        B.func(self)  # 不创建新的实例,调用B类中的绑定方法func
        B().func()  # 创建B类的新实例,调用其绑定方法func


cc = C()
cc.func()

out:
C
A
B
B

实际案例

import pickle
import json


class Mypickle:
    def __init__(self, file):
        self.file = file

    def dump(self, item):
        with open(self.file, mode='ab') as f:
            pickle.dump(item, f)

    def load(self):
        ret = []
        with open(self.file, mode='rb') as f:
            while 1:
                try:
                    ret.append(pickle.load(f))
                except EOFError:
                    break
            return ret


class Myjson:
    def __init__(self, file):
        self.file = file

    def dump(self, item):
        with open(self.file, mode='at', encoding='utf8') as f:
            s = json.dumps(item) + '\n'
            f.write(s)

    def load(self):
        ret = []
        with open(self.file, mode='rt', encoding='utf8') as f:
            for i in f:
                ret.append(json.loads(i))
        return ret


class JsonAndPickle(Myjson, Mypickle):
    def __init__(self, file, select='pickle'):
        select = select.lower()
        if select == 'j' or select == 'json':
            self.select = 'json'
            super().__init__(file)
        else:
            self.select = 'pickle'
            Mypickle.__init__(self, file)

    def dump(self, item):
        if self.select == 'json':
            super().dump(item)
        else:
            Mypickle.dump(self, item)

    @property
    def load(self):
        if self.select == 'json':
            return super().load()
        else:
            return Mypickle.load(self)


p1 = JsonAndPickle('test1.json', 'json')
p1.dump('123abc')
p1.dump(456)
p1.dump(789)
print(p1.load)

p2 = JsonAndPickle('test1.pickle', 'pickle')
p2.dump('123abc')
p2.dump(456)
p2.dump(789)
print(p2.load)

out:
['123abc', 456, 789]
['123abc', 456, 789]

上述案例中定义了Mypickle和Myjson两个类,类中分别定义了dump方法和load方法。

现在又定义了JsonAndPickle类,可以在定义类时传参设置使用json或pickle(默认值)。请注意用super()调用父类Myjson的方法与“类名.方法名(self)”的不同点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值