How to make an iterable class in Python in which only a specific type is allowed to be the element?

这一生的挚爱 提交于 2019-12-25 02:58:30

问题


I want some Python class having similar methods as list (assuming it's called mylist) except that mylist accepts elements of a specific type (instances of another customed class to store some data in my case).

I read some posts on SO and knew that I need to override some methods as append, extend, insert. But I'm not sure about everything I need to override to guarantee that in all operations (e.g. append, add, extend, insert, slice...) to instances of mylist there will be no problem.

And if there is one more convenient way without needs to override so many methods?


回答1:


Sometimes, things are easier without inheriting from builtin objects...:

from collections import MutableSequence, Iterable

class MyList(MutableSequence):
    def __init__(self, type, iterable=()):
        self._data = []
        self._type = type
        self.extend(iterable)

    def insert(self, index, item):
        if not isinstance(item, self._type):
            raise TypeError
        self._data.insert(index, item)

    def __len__(self):
        return len(self._data)

    def __getitem__(self, *args):
        return self._data.__getitem__(*args)

    def __delitem__(self, *args):
        self._data.__delitem__(*args)

    def __setitem__(self, key, value):
         if isinstance(value, collections.Iterable) and isinstance(key, slice):
             values = []
             for val in value:
                 if not isinstance(value, self._type):
                     raise TypeError
         else:
             if not isinstance(value, self._type):
                 raise TypeError
         self._data[k] = value

Note, I haven't gone into any discussion about whether this is a good idea. Some people will tell you not to do this because python is built on "duck-typing". Others say that isinstance is perfectly fine to use -- provided that you do so responsibly. One proponent of this view (Alex Martelli) is generally regarded as a python expert. He recommends isinstance checking against abstract base classes and calls this practice "goose-typing". This practice seems to have gained some traction as the standard library is slowly adding support that would allow more robust run-time checking of these things -- Consider PEP-0484 (type hinting).

I suppose, my point is that if you use this class, don't do:

lst1 = MyList(list)
lst2 = MyList(int)

Do something like:

lst1 = MyList(collections.MutableSequence)
lst2 = MyList(numbers.Integral)


来源:https://stackoverflow.com/questions/32766836/how-to-make-an-iterable-class-in-python-in-which-only-a-specific-type-is-allowed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!