How to do this in Python?

J

Jim Garrison

S said:
class sentinel:
def __eq__(self, other):
return termination_test()

for x in iter(callable, sentinel()):
...

Writing a sensible sentinel.__init__ is left as an exercise....

If I understand correctly, this pattern allows me to create
an object (instance of class sentinel) that implements whatever
equality semantics I need to effect loop termination. In the
case in point, then, I end up with

class sentinel:
def __eq__(self,other):
return other=='' or other==b''

with open(filename, "rb") as f:
for buf in iter(lambda: f.read(1000), sentinel())):
do_something(buf)

i.e. sentinel is really "object that compares equal to both ''
and b''". While I appreciate how this works, I think the
introduction of a whole new class is a bit of overkill for
what should be expressible in iter()
 
L

Luis Zarrabeitia

Quoting Jim Garrison said:
I just tried the code as given above and it results in an infinite loop.

Since f.read() returns a byte string when in binary mode, the sentinel
has to be b''. Is there a value that will compare equal to both '' and b''?

Thank you for the correction.
It works in python2.5 (on my Debian, at least), but I can see why it doesn't in
python3.
It's a shame the iter(o,sentinel) builtin does the
comparison itself, instead of being defined as iter(callable,callable)
where the second argument implements the termination test and returns a
boolean.

A shame indeed. The "takewhile" workaround is way too obfuscated, and to create
a new class only for this purpose is an overkill (and I'd also classify it as
obfuscated).
This would seem to add much more generality... is
it worthy of a PEP?

and, it wouldn't need to replace the current sentinel implementation... one
keyword argument, "predicate", would suffice.

+1.

Cheers,

--
Luis Zarrabeitia
Facultad de Matemática y Computación, UH
http://profesores.matcom.uh.cu/~kyrie


Participe en Universidad 2010, del 8 al 12 de febrero de 2010
La Habana, Cuba
http://www.universidad2010.cu
 
A

afriere

{snip] ... If it
only going to be used once, then just do the usual thing:

f = open(...)
while True:
   buf = f.read()
   if not buf: break
   # whatever.
f.close()

+1

That's the canonical way (maybe using "with ... as" nowadays). Surely
everything else is simply overkill, (or unwarranted cleverness) here.
In any case this is what most practising pythonista would comprehend
instantly.
 
J

Jervis Whitley

What I was wondering
was whether a similar construct was considered for a while loop or even an
if clause, because then the above could be written like this:

 if open(filename, 'rb') as f:
     while f.read(1000) as buf:
         # do something with 'buf'

see here, and the associated bug tracker item.

http://www.python.org/dev/peps/pep-0379/

There is also a thread on python-ideas (sorry no links handy) that
deals with this issue, and the
difference between the use of 'as' and assignment.

This is the PEP that describes the 'with' statement and it goes into
the choice of the 'as' keyword.
http://www.python.org/dev/peps/pep-0343/

(from PEP 343) ..
So now the final hurdle was that the PEP 310 syntax:

with VAR = EXPR:
BLOCK1

would be deceptive, since VAR does *not* receive the value of
EXPR. Borrowing from PEP 340, it was an easy step to:

with EXPR as VAR:
BLOCK1

Cheers,

Jervis
 
B

bieffe62

If I understand correctly, this pattern allows me to create
an object (instance of class sentinel) that implements whatever
equality semantics I need to effect loop termination.  In the
case in point, then, I end up with

     class sentinel:
         def __eq__(self,other):
             return other=='' or other==b''

     with open(filename, "rb") as f:
         for buf in iter(lambda: f.read(1000), sentinel())):
             do_something(buf)

i.e. sentinel is really "object that compares equal to both ''
and b''".  While I appreciate how this works, I think the
introduction of a whole new class is a bit of overkill for
what should be expressible in iter()- Hide quoted text -

- Show quoted text -


In the specific case it should not be needed to create a class,
because
at least with python 2.6:

so you should be able to do:

with open(filename, "rb") as f:
for buf in iter(lambda: f.read(1000), "" ):
do_something(buf)


Ciao
 
J

Josh Holland

There's always some "trollish" behavior in any comp.lang.*
group. Too many people treat languages as religions instead
of tools. They all have strengths and weaknesses :)
If you're referring to my reply (about his pseudocode looking like C), I
hope you realise that it was tongue-in-cheek. For the record, I intend
to learn C in the near future and know it is a very powerful language.
How people would write a kernel in Python?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,294
Messages
2,571,511
Members
48,203
Latest member
LillianaFr

Latest Threads

Top