Last iteration?
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Fri Oct 19 20:15:12 EDT 2007
En Fri, 19 Oct 2007 19:12:49 -0300, Michael J. Fromberger
<Michael.J.Fromberger at Clothing.Dartmouth.EDU> escribió:
> Before I affront you with implementation details, here's an example:
>
> | from __future__ import with_statement
>
> | with last_of(enumerate(file('/etc/passwd', 'rU'))) as fp:
> | for pos, line in fp:
> | if fp.marked():
> | print "Last line, #%d = %s" % (pos + 1, line.strip())
>
> In short, last_of comprises a trivial context manager that knows how to
> iterate over its input, and can also indicate that certain elements are
> "marked". In this case, only the last element is marked.
The name is very unfortunate. I'd expect that last_of(something) would
return its last element, not an iterator.
Even with a different name, I don't like that marked() (a method of the
iterator) should be related to the current element being iterated.
> We could also make the truth value of the context manager indicate the
> marking, as illustrated here:
>
> | with last_of("alphabet soup") as final:
> | for c in final:
> | if final:
> | print "Last character: %s" % c
>
> This is bit artificial, perhaps, but effective enough. Of course, there
Again, why should the trueness of final be related to the current element
being iterated?
> is really no reason you have to use "with," since we don't really care
> what happens when the object goes out of scope: You could just as
> easily write:
>
> | end = last_of(xrange(25))
> | for x in end:
> | if end:
> | print "Last element: %s" % x
Again, why the truth value of "end" is related to the current "x" element?
> But you could also handle nested context, using "with". Happily, the
> machinery to do all this is both simple and easily generalized to other
> sorts of "marking" tasks. For example, we could just as well do
> something special with all the elements that are accepted by a predicate
> function, e.g.,
>
> | def isinteger(obj):
> | return isinstance(obj, (int, long))
>
> | with matching(["a", 1, "b", 2, "c"], isinteger) as m:
> | for elt in m:
> | if m.marked():
> | print '#%s' % elt,
> | else:
> | print '(%s)' % elt,
> |
> | print
I think you are abusing context managers *a*lot*!
Even accepting such evil thing as matching(...), the above code could be
equally written as:
m = matching(...)
for elt in m:
...
Anyway, a simple generator that yields (elt, function(elt)) would be
enough...
--
Gabriel Genellina
More information about the Python-list
mailing list