Newbie: Why doesn't this work

Gabriel Genellina gagsl-py2 at
Wed Jan 2 06:14:22 CET 2008

En Wed, 02 Jan 2008 01:11:12 -0300, <petr.jakes.tpc at> escribió:

> I am trying to experiment a little bit with new-style class and I am
> confused why following example always returns 0 (zero). I was
> expecting <generator object> will return values from 0 to 9 and finaly
> an Exception.
> class GenExample(object):
>     def getInfo(self):
>         for no in range(10):
>             yield no
>     myNo=property(getInfo)
> gen=GenExample()
> print
> print
> .
> .
> print

Doing it this way, works as intended:

py> gen=GenExample()
py> myNo = gen.myNo
py> print
py> print
py> print
py> print
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>

Why? I've seen you have read about the descriptor protocol. Methods are  
implemented as non-data descriptors. When you retrieve the "myNo"  
attribute from the "gen" instance, a bound method is created, combining  
the original getInfo function (stored into the class) with the gen  
instance. This is done *each* time the attribute is retrieved, and each  
time you get a different method object. That's why in your original  
example you always got 0: all methods are newly created ones, starting the  
iteration. (After the call finishes, as nobody holds any additional  
reference to it, the method object becomes a candidate to be garbage  
collected and eventually is deleted)

Now it should be clear why my example above does work: I'm using always  
the *same* method object, previously saved into the "myNo" variable.

This also explains a popular optimization technique: move attribute  
lookups out of a critical loop. That is, transforming this:

for item in container:

into this:

writerecord = out.writerecord
for item in container:

Of course this should NOT be done blindly.

Gabriel Genellina

More information about the Python-list mailing list