如何实现一个最小的类,使其在Python中像序列一样工作?
我在寻找一个简单的示例,展示一个在Python中模拟不可变序列的类。
class MySequence()
...
a = MySequence()
len(a)
for i in a:
pass
a[0]
需要实现哪些方法呢?
2 个回答
6
补充一下@Jeremy的回答:一个常用的方法来检查一个值是否是一个通用序列,就是用 isinstance(value, collections.Sequence)
。
为了让你的类型也能通过这个检查,它需要继承自 collections.Sequence
。这样做的好处是,它会提供迭代器(还有一些其他有用的功能),只要你实现了 __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]
14
如果你只是想让你的序列可以被遍历,那你只需要实现一个叫做 __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__
方法。)