En Wed, 02 Jan 2008 01:11:12 -0300, <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list