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