无法在Python中遍历列表类

6 投票
3 回答
5383 浏览
提问于 2025-04-15 21:41

我正在尝试用pyplurk为Plurk写一个简单的图形界面前端。

我已经成功建立了API连接,登录,并获取并显示了朋友列表。现在我想获取并显示Plurk的列表。

pyplurk提供了一个叫GetNewPlurks的功能,具体如下:

  def GetNewPlurks(self, since):
    '''Get new plurks since the specified time.
    Args:
      since: [datetime.datetime] the timestamp criterion.
    Returns:
      A PlurkPostList object or None.
    '''
    offset = jsonizer.conv_datetime(since)
    status_code, result = self._CallAPI('/Polling/getPlurks', offset=offset)
    return None if status_code != 200 else \
           PlurkPostList(result['plurks'], result['plurk_users'].values())

如你所见,这个功能返回了一个PlurkPostList,而这个PlurkPostList又是这样定义的:

class PlurkPostList:
  '''A list of plurks and the set of users that posted them.'''
  def __init__(self, plurk_json_list, user_json_list=[]):
    self._plurks = [PlurkPost(p) for p in plurk_json_list]
    self._users = [PlurkUser(u) for u in user_json_list]
  def __iter__(self):
    return self._plurks
  def GetUsers(self):
    return self._users
  def __eq__(self, other):
    if other.__class__ != PlurkPostList: return False
    if self._plurks != other._plurks: return False
    if self._users != other._users: return False
    return True

现在我本来以为可以这样做:

api = plurk_api_urllib2.PlurkAPI(open('api.key').read().strip(), debug_level=1)
plurkproxy = PlurkProxy(api, json.loads)
user = plurkproxy.Login('my_user', 'my_pass')
ps = plurkproxy.GetNewPlurks(datetime.datetime(2009, 12, 12, 0, 0, 0))
print ps
for p in ps:
  print str(p)

但是当我运行这个代码时,实际上得到的是:

<plurk.PlurkPostList instance at 0x01E8D738>

从“print ps”中,我得到了:

    for p in ps:
TypeError: __iter__ returned non-iterator of type 'list'

我不明白——列表不应该是可以遍历的吗?我哪里出错了——我该如何访问PlurkPostList中的Plurk?

3 个回答

0

另外,你也可以定义一个叫做 next() 的函数,然后让 __iter__() 返回自己。想要了解更多,可以看看这个链接:构建一个基本的Python迭代器,里面有个不错的例子。

5

这个 __iter__ 方法应该返回一个实现了 next() 方法的对象。

列表本身没有 next() 方法,但它有一个 __iter__ 方法,这个方法会返回一个 listiterator 对象。而这个 listiterator 对象是有 next() 方法的。

你应该这样写:

def __iter__(self):
    return iter(self._plurks)
14

当你自己定义一个 __iter__ 方法时,你需要明白这个方法应该返回一个 迭代器,而不是一个 可迭代对象。简单来说,你返回的是一个列表,而不是指向这个列表的迭代器,所以会出错。你可以通过返回 iter(self._plurks) 来解决这个问题。

如果你想做一些更复杂的事情,比如在遍历 self._plurks 的时候处理每一个项目,通常的做法是让你的 __iter__ 方法成为一个 生成器。这样,调用 __iter__ 方法时返回的就是这个生成器,而生成器本身就是一个迭代器:

def __iter__(self):
    for item in self._plurks:
        yield process(item)

撰写回答