我正在寻找一个模拟Python中不可变序列的类的示例最小示例。
class MySequence()
...
a = MySequence()
len(a)
for i in a:
pass
a[0]
有哪些方法必须实施?
如果您只想迭代序列,则只需要实现返回可迭代的__iter__
方法。最简单的方法是使用yield
语句创建生成器。
class MySequence(object):
def __iter__(self):
yield 1
yield 2
yield 3
for x in MySequence():
print x # prints 1, then 2, then 3
但是,这不会启用像MySequence()[1]
这样的东西。为此你需要实现__getitem__
方法,并且应该也可以实现__len__
。
class MySequence(object):
def __len__(self):
return 3
def __getitem__(self, key):
if key == 0:
return 1
elif key == 1:
return 2
elif key == 2:
return 3
else:
raise IndexError()
s = new MySequence()
for i in range(len(s)):
print s[i] # prints 1, then 2, then 3
for x in s:
print x # prints 1, then 2, then 3
请注意,我省略了__iter__
。只要__getitem__
在尝试获得超出范围的值时引发IndexError
,Python就可以使用它进行迭代。 (如果我想要更清楚,或者想要非标准的迭代行为,我仍然可以包括__iter__
。)
添加到@ Jeremy的答案:值是一般序列的流行检查是使用isinstance(value, collections.Sequence)
。
为了使你的类型成为真,它需要从collections.Sequence
继承,这实际上为mixins提供了迭代器(以及一些其他有用的函数),只要你提供__len__
和__index__
函数。
借用@ Jeremy的答案,一个示例类看起来像:
import collections
class MySequence(collections.Sequence):
def __len__(self):
return 3
def __getitem__(self, key):
if key == 0:
return 1
elif key == 1:
return 2
elif key == 2:
return 3
else:
raise IndexError()
用法示例:
s = MySequence()
for i in range(len(s)):
print s[i] # prints 1, then 2, then 3
for x in s:
print x # prints 1, then 2, then 3
print isinstance(s, collections.Sequence) # prints True
print 1 in s # prints True
print list(reversed(s)) # prints [3, 2, 1]