[Edu-sig] Scratch pad nuttiness... (re generators)

kirby urner kirby.urner at gmail.com
Mon Mar 16 18:30:50 CET 2009


On Mon, Mar 16, 2009 at 9:38 AM, John Zelle <john.zelle at wartburg.edu> wrote:

>> = Kirby
> = John
 = Kirby

>> Simple solution:
>> >>> def kick(o):
>>
>>       return next(o)
>
> Of couse, the simplest solution is just to bind kick to next:
>
>>>> o = iter(range(10))
>>>> kick = next
>>>> kick(o)
> 0
>>>> kick(o)
> 1
>
> That does the trick.
>

Yeah, that's a good one.  A naive student would think range is already
an iter, "so why are we making an iter and iter?" is what they'll be
thinking.  More important, you're showing that 'next' is in the
toplevel namespace in Python 3.x, and available for reassignment or
"shared assignment" (as kick becomes a synonym for next, not a
replacement).

>> Another student might think different and try something like this:
>> >>> o.__next__
>>
>> <method-wrapper '__next__' of generator object at 0x8367edc>
>>
>> >>> o.kick = o.__next__
>>
>> Traceback (most recent call last):
>>   File "<pyshell#51>", line 1, in <module>
>>     o.kick = o.__next__
>> AttributeError: 'generator' object has no attribute 'kick'
>>
>> "Dang, you can't give your generator object a random attribute i
>> doesn't already have, write-protected in some way...."
>
> Of course, even if this worked, it wouldn't give you the kick(o) behavior that
> you specified above. I could see where one might try this to get the 2.xish
> o.kick() behavior. Of course, you could easily get an alias to o's __next__
> via simple assignment again:

Yes, the student would then have o.kick() seeming to work just as __next__
does, then still have to snap out of the 2.x trance and think next is something
you have to "write home about" (add to the toplevel namespace).

In 2.5:

IDLE 1.2.2
>>> help(next)

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    help(next)
NameError: name 'next' is not defined

In 3.0:

>>> help(next)
Help on built-in function next in module builtins:

next(...)
    next(iterator[, default])

    Return the next item from the iterator. If default is given and the iterator
    is exhausted, it is returned instead of raising StopIteration.

>>>

In retrospect, I'd say a lesson for all students is:  consult builtin
docs a lot right in the shell, get in that habit, because then you'll
hold yourself to the same habits, i.e. if you module is not
help-aware, then you're cheating your readers, and actually yourself,
your chief reader perhaps...

Python is generous out of the box, is a good role model of
developer-friendly (not the same as newbie friendly, but then that's
the job of developers (to welcome apprentice snake charmers into the
fold with open arms -- something the Python community is already known
for (its welcoming aspect))).

>> >>> class newgen (type(o)):
>>
>>       kick = type(o).__next__
>>
>>
>> Traceback (most recent call last):
>>   File "<pyshell#10>", line 1, in <module>
>>     class newgen (type(o)):
>> TypeError: type 'generator' is not an acceptable base type
>
> I don't follow the reasoning in this attempt at all.
>
> --John

This is a student thinking "oh, if a primitive thingy doesn't do what
I want it to, I should subclass it and add my new method".  So here
said student is trying to subclass the "generator type" by using
type(some_class) as a way of saying "what to inherit from" and then
trying the same trick as before, except reaching into the superclass
for whatever that __next__ thingy is.

Kirby


More information about the Edu-sig mailing list