[Python-Dev] code blocks using 'for' loops and generators

Brian Sabbey sabbey at u.washington.edu
Sun Mar 13 02:43:23 CET 2005


On Sat, 12 Mar 2005, Steven Bethard wrote:
> Brian Sabbey <sabbey at u.washington.edu> wrote:
>> I agree that this is a confusing way to use generators.  But it is the
>> expected way to use "code blocks" as found in other languages.  It would
>> take some getting used to that 'for' can be used this way, but I think it
>> would be worth it.
>
> I guess I need some more convincing...  I don't find your approach[*], e.g.
>
> def pickled_file(name):
>    f = open(name, 'r')
>    data yield pickle.load(f)
>    f.close()
>    f = open(name, 'w')
>    pickle.dump(data, f)
>    f.close()
>
> for data in pickled_file('greetings.pickle'):
>    data.append('hello')
>    data.append('howdy')
>    continue data
>
> any clearer than, say:
>
> class PickledFile(object):
>     def __init__(self, name):
>         self.name = name
>         f = open(self.name, 'r')
>         self.data = pickle.load(f)
>         f.close()
>     def close(self):
>         f = open(self.name, 'w')
>         pickle.dump(self.data, f)
>         f.close()
>
> p = PickledFile('greetings.pickle')
> p.data.extend(['hello', 'howdy'])
> p.close()
>
> Note that I'm not using the iteration construct (for-in) because I'm
> not really doing an iteration here.  Pehaps I could be taught to read
> for-in otherwise, but without an obvious benefit for doing so, I'm
> really not inclined to.

In the real world, I need to lock and unlock the pickled files.  So if I 
forget to call p.close(), then it would be a problem.  I would need a 
try/finally block.  If I could use the above 'for' loop approach, I am 
able to encapsulate the try/finally code.

This is the same problem that is addressed in PEP 310.  Copied from the 
PEP, here is the basic idea:

    The syntax of a 'with' statement is as follows::

 	'with' [ var '=' ] expr ':'
 	    suite

     This statement is defined as being equivalent to the following
     sequence of statements:

 	var = expr

 	if hasattr(var, "__enter__"):
 	    var.__enter__()

 	try:
 	    suite

 	finally:
             var.__exit__()

I prefer re-using the 'for' loop for this purpose because it allows the 
problem to be solved in a general way by re-using a structure with which 
most users are already familiar, and uses generators, which are easier to 
use in this case than defining a class with __exit__, __enter__, etc.

-Brian


More information about the Python-Dev mailing list