Alternative iterator syntax

Tim Hochberg tim.hochberg at ieee.org
Wed Feb 21 14:24:28 EST 2001


"Michael Hudson" <mwh21 at cam.ac.uk> wrote in message
news:m37l2kszu7.fsf at atrus.jesus.cam.ac.uk...
> aahz at panix.com (Aahz Maruch) writes:
>
> > In article <mailman.982769240.31345.python-list at python.org>,
> > Huaiyu Zhu  <hzhu at users.sourceforge.net> wrote:
> > >
> > >  [...]
> >
> > I'm not sure where to put this question, so I'm just deleting all of
> > Huaiyu's text.
> >
> > How does one get UserDict.keys (note: no parens here) to return an
> > iterator?  Normally this will simply return a reference to the method.
>
> class _Keys:
>    def __init__(self, dict):
>        self.dict = dict
>    def __contains__(self, item):
>        return self.dict.has_key(item)
>    def __call__(self):
>        return self.dict.keys()
>    ... etc ...
>
> class UserDict:
>     def __init__(self, dict=None):
>         if data is None:
>             data = {}
>         self.data = dict
>         self.keys = _Keys(dict)
>         ... etc ...
>
> Not *very* different from how you'd implement this in C, really.
>
> Hmm, you might want to have the _Keys object hang on the instance
> rather than the dict if assigning to the .data member of UserDict is
> allowed.  Which would create a circular reference, but we don't have
> to worry about that too much now...

I don't think this will work right though. Consider:

for k in aUserDict.keys:
   # Do some stuff
for k in aUserDict.keys:
    # Do some more stuff

The way this is implemented here the second loop would bail out immediately
because there is only a single iterator for a given instance and it is
already exhausted. One could imagine even odder instances where one broke
out halfway through the first loop; the second loop would then start
iterating halfway through the dictionaries keys. To get this to work "right"
one would need to generate a new iterator using getattr magic every time the
attribute was asked. Something like:

def UserDict:
   def __attr_keys_(self, op, value):
      if "op" == "get": return _Keys(dict)
      else: raise ValueError("keys not writable")

Here I've used the syntax from the draft "Attribute Access Handlers" PEP.
This makes the keys attribute sufficiently magical that it makes me a bit
nervous. On the other hand, one could do kinda cool stuff like:

myKeys = aUserDict.keys # Get my own copy of the keys iterator
for key in myKeys:
    # Do Stuff
    if key == someSpecialKey:
        break
# Do some processing out of the loop
for key in myKeys: # resume where we left off
    # Do some other stuff

Sure that example's a little contrived, but I'm sure that must be usefule
somewhere <0.8 wink>.

-tim







More information about the Python-list mailing list