Unable to iterate over list class in Python

I am trying to write a simple GUI for Plurk using pyplurk.

I successfully received it to create an API connection, log in and get and display a list of friends. Now I'm trying to get and display a list of Plurks.

pyplurk provides the GetNewPlurks function as follows:

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()) 

As you can see, this returns a PlurkPostList, which in turn is defined as follows:

 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 

Now I expected that I could do something like this:

 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) 

When I run this, I get the following:

 <plurk.PlurkPostList instance at 0x01E8D738> 

from "print ps", then:

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

I don’t understand - for sure the list is repeated? Where am I mistaken - how do I access Plurks in a PlurkPostList?

+6
python
source share
3 answers

When you define your own __iter__ method, you should understand that this __iter__ method should return an iterator, not an iterable. You are returning a list, not an iterator, to the list, so it fails. You can fix this by doing return iter(self._plurks) , for example.

If you want to do something more complex, for example, process each element in self._plurks as it repeats itself, the usual trick is to make your __iter__ method a generator. Thus, the returnvalue of the __iter__ call is a generator, which is an iterator:

 def __iter__(self): for item in self._plurks: yield process(item) 
+14
source share

The __iter__ method should return an object that implements the next() method.

There is no next() method in the list, but it has a __iter__ method that returns a listiterator object. The listiterator object has a next() method.

You must write:

 def __iter__(self): return iter(self._plurks) 
+5
source share

Alternatively, you can also define the next() function and return __iter__() self. See Build a Basic Python Iterator for a nice example.

0
source share

All Articles