如何在Python中创建一个只允许特定类型作为元素的iterable类?

如何在Python中创建一个只允许特定类型作为元素的iterable类?,python,class,python-2.7,Python,Class,Python 2.7,我希望一些Python类具有与list类似的方法(假设它被称为mylist),除了mylist接受特定类型的元素(另一个自定义类的实例在我的示例中存储一些数据) 我在SO上读了一些帖子,知道我需要重写一些方法,如append,extend,insert。但我不确定需要覆盖哪些内容,以确保在mylist实例的所有操作(例如追加、添加、扩展、插入、切片…)中都不会出现问题 如果有一种更方便的方法不需要覆盖这么多方法?有时,如果不继承内置对象,事情会变得更容易…: from collections i

我希望一些Python类具有与
list
类似的方法(假设它被称为
mylist
),除了
mylist
接受特定类型的元素(另一个自定义类的实例在我的示例中存储一些数据)

我在SO上读了一些帖子,知道我需要重写一些方法,如
append
extend
insert
。但我不确定需要覆盖哪些内容,以确保在
mylist
实例的所有操作(例如追加、添加、扩展、插入、切片…)中都不会出现问题


如果有一种更方便的方法不需要覆盖这么多方法?

有时,如果不继承内置对象,事情会变得更容易…:

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

注意,我没有讨论过这是否是个好主意。有些人会告诉您不要这样做,因为python是建立在“duck-typing”之上的。另一些人说,
isinstance
非常好用——只要你负责任地这么做。这种观点的一个支持者(Alex Martelli)通常被认为是python专家。他建议对抽象基类进行
isinstance
检查,并将这种做法称为“goosetyping”。由于标准库正在慢慢添加支持,这些支持将允许对这些事情进行更健壮的运行时检查——考虑(类型提示)。 我想,我的观点是,如果你使用这个类,不要:

lst1 = MyList(list)
lst2 = MyList(int)
做一些类似于:

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

有时,如果不继承内置对象,事情会变得更简单…:

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

注意,我没有讨论过这是否是个好主意。有些人会告诉您不要这样做,因为python是建立在“duck-typing”之上的。另一些人说,
isinstance
非常好用——只要你负责任地这么做。这种观点的一个支持者(Alex Martelli)通常被认为是python专家。他建议对抽象基类进行
isinstance
检查,并将这种做法称为“goosetyping”。由于标准库正在慢慢添加支持,这些支持将允许对这些事情进行更健壮的运行时检查——考虑(类型提示)。 我想,我的观点是,如果你使用这个类,不要:

lst1 = MyList(list)
lst2 = MyList(int)
做一些类似于:

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

self.\u data.index(index,item)
应该是
self.\u data.insert(index,item)
self.extend(iterable)
be
self.\u data.extend(iterable)
?我没有最后的例子。他们是否打算将类型从MutableSequence转换为MyList?@Dr.Lee否。如果您确实执行了
self.\u data.extend(iterable)
,则这些元素将未经检查进入您的数据列表。使用
self.extend
确保正确检查它们(尽管默认实现可能没有您自己编写的那么有效)。@Dr.Lee关于最后的示例,
lst1=MyList(list)
确保您放入的任何元素都是
列表(或
list
的子类)。但是,正如我在这里演示的,使用
集合.MutableSequence
创建类似列表的东西非常容易——因此最好检查类似
列表的东西,而不是检查该东西是否是
列表。(注意,
isinstance([],collections.MutableSequence)
True
),我知道了。非常感谢。
self.\u data.index(index,item)
应该是
self.\u data.insert(index,item)
self.extend(iterable)
be
self.\u data.extend(iterable)
?我没有最后的例子。他们是否打算将类型从MutableSequence转换为MyList?@Dr.Lee否。如果您确实执行了
self.\u data.extend(iterable)
,则这些元素将未经检查进入您的数据列表。使用
self.extend
确保正确检查它们(尽管默认实现可能没有您自己编写的那么有效)。@Dr.Lee关于最后的示例,
lst1=MyList(list)
确保您放入的任何元素都是
列表(或
list
的子类)。但是,正如我在这里演示的,使用
集合.MutableSequence
创建类似列表的东西非常容易——因此最好检查类似
列表的东西,而不是检查该东西是否是
列表。(注意,
isinstance([],collections.MutableSequence)
True
),我知道了。谢谢。