Newbie: Why doesn't this work

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Wed Jan 2 06:14:22 CET 2008


En Wed, 02 Jan 2008 01:11:12 -0300, <petr.jakes.tpc at gmail.com> 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 gen.myNo.next()
> print gen.myNo.next()
> .
> .
> print gen.myNo.next()

Doing it this way, works as intended:

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

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:
     out.writerecord(item)

into this:

writerecord = out.writerecord
for item in container:
     writerecord(item)

Of course this should NOT be done blindly.

-- 
Gabriel Genellina




More information about the Python-list mailing list