views:

147

answers:

4

my code run wrong

class a(object):
    def __iter(self):
        return 33
b={'a':'aaa','b':'bbb'}
c=a()
print b.itervalues()
print c.itervalues()

Please try to use the code, rather than text, because my English is not very good, thank you

+3  A: 

a. Spell it right: not

   def __iter(self):

but:

   def __iter__(self):

with __ before and after iter.

b. Make the body right: not

return 33

but:

yield 33

or return iter([33])

If you return a value from __iter__, return an iterator (an iterable, as in return [33], is almost as good but not quite...); or else, yield 1+ values, making __iter__ into a generator function (so it intrinsically returns a generator iterator).

c. Call it right: not

a().itervalues()

but, e.g.:

for x in a(): print x

or

print list(a())

itervalues is a method of dict, and has nothing to do with __iter__.

If you fix all three (!) mistakes, the code works better;-).

Alex Martelli
But if he's just returning (yielding) 33, is that really an *iterator*?
Goose Bumper
Well, if you **yield** 33, then yes, then the method becomes a generator expression, that yields an iterator. When you return [33], well, a list is certainly iterable, so it works too.
shylent
@Goose and @Shylent, yep: `yield 33` makes `__iter__` a generator function (**not** generator _expression_ -- that's a different construct;-), so it returns a generator, which is an iterator; `return [33]` returns an iterable but not an iterator, so that's slightly imperfect -- editing answer to fix that quibble!-)
Alex Martelli
Oh, you are of course right about generator **function** vs generator **expression**, don't know what I've been thinking while writing that.
shylent
A: 

You are using this language feature incorrectly.

http://docs.python.org/library/stdtypes.html#iterator-types

This above link will explain what the function should be used for.

You can try to see documentation in your native language here: http://wiki.python.org/moin/Languages

wlashell
+4  A: 

A few things about your code:

  1. __iter should be __iter__
  2. You're returning '33' in the __iter__ function. You should actually be returning an iterator object. An iterator is an object which keeps returning different values when it's next() function is called (maybe a sequence of values like [0,1,2,3 etc]).

Here's a working example of an iterator:

class a(object):
    def __init__(self,x=10):
     self.x = x
    def __iter__(self):
     return self
    def next(self):
     if self.x > 0:
      self.x-=1
      return self.x
     else:
      raise StopIteration

c=a()

for x in c:
    print x

Any object of class a is an iterator object. Calling the __iter__ function is supposed to return the iterator, so it returns itself – as you can see, the a class has a next() function, so this is an iterator object.

When the next function is called, it keeps return consecutive values until it hits zero, and then it sends the StopIteration exception, which (appropriately) stops the iteration.

If this seems a little hazy, I would suggest experimenting with the code and then checking out the documentation here: http://docs.python.org/library/stdtypes.html

Goose Bumper
A: 

Here is a code example that implements the xrange builtin:

class my_xrange(object):
    def __init__(self, start, end, skip=1):
        self.curval = int(start)
        self.lastval = int(end)
        self.skip = int(skip)
        assert(int(skip) != 0)

    def __iter__(self):
        return self

    def next(self):
        if (self.skip > 0) and (self.curval >= self.lastval):
            raise StopIteration()
        elif (self.skip < 0) and (self.curval <= self.lastval):
            raise StopIteration()
        else:
            oldval = self.curval
            self.curval += self.skip
            return oldval

for i in my_xrange(0, 10):
    print i
Omnifarious
what's this code mean. assert(int(skip) != 0)
zjm1126
That tells Python to throw an exception if skip is 0. If skip is 0 the iterator will never terminate and will always print out the same value.
Omnifarious
It is not necessary and is only there to make the class safer to use. It can be removed without harm.
Omnifarious