继承Python标准类

-- TOC --

我们可以通过继承Python标准类来创建自己的个性化的list,dict,set等对象。override标准接口,或新增接口。

For a long time, it was impossible to inherit directly from Python types implemented in C. Python 2.2 fixed this issue. Now you can subclass built-in types, including list.

继承list

下面是两个继承list类的case:

non-raise remove

下面的代码,myList继承标准list,重写remove接口,使得remove一个不存在的value的时候,不要raise,并增加一个rshow接口,逆序的方式显示所有元素:

class myList(list):

    def remove(self, x):
        try:
            super().remove(x)
        except ValueError:
            pass

    def rshow(self):
        print(self[::-1])
>>> a = myList((1,2,3))
>>> a.remove(4)  # no raise
>>> a
[1, 2, 3]
>>> a.remove(2)
>>> a
[1, 3]
>>> a.remove(2)  # no raise
>>> a
[1, 3]
>>> a.rshow()
[3,1]

string_list

通过继承list类,创建一个只保存string的list类。

class StringList(list):
    def __init__(self, iterable):
        super().__init__(str(item) for item in iterable)

    def __setitem__(self, index, item):
        super().__setitem__(index, str(item))

    def insert(self, index, item):
        super().insert(index, str(item))

    def append(self, item):
        super().append(str(item))

    def extend(self, other):
        if isinstance(other, type(self)):
            super().extend(other)
        else:
            super().extend(str(item) for item in other)

StringList的定义,每个接口都在调用super,但是传入的参数都经过了str处理。init和extend都使用了list comprehension创建generator的技巧。(这里的StringList,不支持+操作符,要支持的话,需要override更多接口)

测试如下:

>>> from string_list import StringList
>>> data = StringList([1, 2, 2, 4, 5])
>>> data
['1', '2', '2', '4', '5']
>>> data.append(6)
>>> data
['1', '2', '2', '4', '5', '6']
>>> data.insert(0, 0)
>>> data
['0', '1', '2', '2', '4', '5', '6']
>>> data.extend([7, 8, 9])
>>> data
['0', '1', '2', '2', '4', '5', '6', '7', '8', '9']
>>> data[3] = 3
>>> data
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

类似这样的方法,我们还可以创建其它限制数据类型的list类。

关于UserList

新代码肯定不会在用UserList了,下面的内容了解一下即可:

Another way to create a custom list-like class is to use the UserList class from the collections module. This class is a wrapper around the built-in list type. It was designed for creating list-like objects back when it wasn’t possible to inherit from the built-in list class directly.

Even though the need for this class has been partially supplanted by the possibility of directly subclassing the built-in list class, UserList is still available in the standard library, both for convenience and for backward compatibility.

The distinguishing feature of UserList is that it gives you access to its .data attribute, which can facilitate the creation of your custom lists because you don’t need to use super() all the time. The .data attribute holds a regular Python list, which is empty by default.

继承set

下面的代码,mySet继承标准set,并重写add接口,使得只能add奇数,而当出现偶数时,啥也不干:

class mySet(set):

    def add(self, x):
        if x%2 in (-1,1):
            super().add(x)
>>> b = mySet()
>>> b.add(1)
>>> b.add(2)
>>> b.add(3)
>>> b
mySet({1, 3})

当然,也可以增加自定义的接口!

本文链接:https://cs.pynote.net/sf/python/202204031/

-- EOF --

-- MORE --