我正在寻找一个Python中模仿不可变序列的类的简单示例。
必须实现哪些方法?
class MySequence()
...
a = MySequence()
len(a)
for i in a:
pass
a[0]
必须实现哪些方法?
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__
。)
print x
。 - sorin补充@Jeremy的回答:检查值是否为通用序列的一种流行方法是使用isinstance(value, collections.Sequence)
。
为了使您的类型成为通用序列,它需要继承自collections.Sequence
,并且这实际上提供了迭代器(和其他一些有用的函数)作为mixin,只要您提供了__len__
和__getitem__
函数。
借鉴@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]