I know that I can do (2), but it operates on the whole list and the original
may break out early. I want the efficiency of (1), but the conciseness of (2).
2)
return True in map(test,xs)
Makes it obvious that there is a way for the iternation to end early.
> 2)
> return True in map(test,xs)
Strongly implies ("foo in list", "map()") that the entire list will be
iterated. Any other behaviour would be unexpected to the person reading
the code.
> I know that I can do (2), but it operates on the whole list and the
> original may break out early. I want the efficiency of (1), but the
> conciseness of (2).
I think that in seeking to make it more concise, you're also seeking to
make it less obvious. Anything that has the semantics of "loop over the
whole list" in a single statement, isn't going to help people understand
that a common case is for the iteration to end early. Which is probably
a good reason for it not to appear.
If you want to hide the algorithm, do so inside a helper function. Then
you have consision in the places where you're actually using it, and
explicit semantics where the algorithm is implemented.
--
\ "A cynic is a man who, when he smells flowers, looks around for |
`\ a coffin." -- Henry L. Mencken |
_o__) |
Ben Finney <http://bignose.squidly.org/>
On second look, you appear to *be* putting this in a helper function,
presumably for the purpose of hiding the implementation. If so, it's a
good thing that the implementation is explicit here -- anyone who goes
looking into this function wants it obvious how it works.
--
\ "When I get real bored, I like to drive downtown and get a |
`\ great parking spot, then sit in my car and count how many |
_o__) people ask me if I'm leaving." -- Steven Wright |
Ben Finney <http://bignose.squidly.org/>
That's not quite the same, unless you guarantee that test(x)==bool(test(x))==True when
test(x) is logically true, and never returns True otherwise. (E.g., what if test were
def test(x): return x ? f(range(5)) will give you a True when you hit 1 but, map(test,range(5))
will just be the numbers, and there will be no True in that).
I guess with generator expressions you will soon be able to write
def f(xs): return True in (bool(test(x)) for x in xs)
We can fake the generator expression and a test that will show us how far it went, to see...
>>> def test(x): print x; return x=='3'
...
(Ok, that does guarantee a bool, but some other test might conceivably not).
>>> def gx(fun, seq):
... for x in seq: yield bool(fun(x))
...
>>> xs = 'abc123def456'
and
>>> def f(xs): return True in gx(test, xs)
...
>>> f(xs)
a
b
c
1
2
3
True
Regards,
Bengt Richter
--
Georgy Pruss
E^mail: 'ZDAwMTEyMHQwMzMwQGhvdG1haWwuY29t\n'.decode('base64')
"MetalOne" <j...@iteris.com> wrote in message news:92c59a2c.03111...@posting.google.com...
Actually, when I word it that way, I guess what I want is PEP 289,
universal and existential qualifiers.
I guess I'll have to wait.
[2] is quite different [1] in terms of semantics, of course. [1] will
accept any true (non-false) result, such as 23 or 'foo', [2] won't. If
[2]'s semantics are what you want,
return True in itertools.imap(test, xs)
should give you exactly what you require. Otherwise, you may want to
ensure a 'bool' is further applied, either by using a lambda or by
nesting two imap calls.
Alex
Sure there is. The code that you showed was an excellent way to do
so.
> Actually, when I word it that way, I guess what I want is PEP 289,
> universal and existential qualifiers.
>
> I guess I'll have to wait.
Why? Why not just stuff the code you wrote into an appropriately
named function and use that?
Anyway, here are more efficient implementations:
def any(p, seq):
"""Returns true if any element in seq satisfies predicate p."""
for elt in itertools.ifilter(p, seq):
return True
else:
return False
def all(p, seq):
"""Returns true if all elements in seq satisfy predicate p."""
for elt in itertools.ifilterfalse(p, seq):
return False
else:
return True
Jeremy
return True in itertools.imap(test,xs) ?
M.
This is a perfect example of why I dislike the "else" clause. I
would code this as
def any(p, seq):
"""Returns true if any element in seq satisfies predicate p."""
for elt in itertools.ifilter(p, seq):
return True
return False
def all(p, seq):
"""Returns true if all elements in seq satisfy predicate p."""
for elt in itertools.ifilterfalse(p, seq):
return False
return True
Since the "else" is unnecessary, it disturbs me, I get confused,
I don't see why it is used (there is no break in the loop) and the
code becomes much harder to read, for me. OTOH I am sure 99% of
people would say "look, it is obvious, if elt is in the output
of ifilter it will return True, else False (viceversa in the
second case)". But may brain sees that the "else" is unncessary
and immediately it is disturbed by th redundance.
Am I the only one? ;)
Michele
> Am I the only one? ;)
I think such code is likely to fool people into thinking that the else part of
loops is only executed if no single iteration takes place.
'as
> > def all(p, seq):
> > """Returns true if all elements in seq satisfy predicate p."""
> > for elt in itertools.ifilterfalse(p, seq):
> > return False
> > return True
> >
> I'd be wasting a local with
>
> def any(p, seq):
> """ibid"""
> a = False
> for elt in itertools.ifilter(p, seq):
> a = True
break
> return a
You're not just wasting a local.
'as
> j...@iteris.com (MetalOne) wrote in message news:<92c59a2c.03111...@posting.google.com>...
> > Maybe my post was not clear.
> > I want a means to test if there exists an element in the list that
> > satisfies a predicate.
>
> Sure there is. The code that you showed was an excellent way to do
> so.
>
> > Actually, when I word it that way, I guess what I want is PEP 289,
> > universal and existential qualifiers.
> >
> > I guess I'll have to wait.
>
> Why? Why not just stuff the code you wrote into an appropriately
> named function and use that?
>
> Anyway, here are more efficient implementations:
>
> def any(p, seq):
> """Returns true if any element in seq satisfies predicate p."""
> for elt in itertools.ifilter(p, seq):
> return True
> else:
> return False
Another alternative (also works for python2.2, but is likely to be slower):
def some(predicate, *seqs):
iterables = map(iter, seqs)
try:
while 1:
boo = predicate(*[iterable.next() for iterable in iterables])
if boo: return boo
except StopIteration: return False
'as
>def any(p, seq):
> """Returns true if any element in seq satisfies predicate p."""
> for elt in itertools.ifilter(p, seq):
> return True
> return False
>
>def all(p, seq):
> """Returns true if all elements in seq satisfy predicate p."""
> for elt in itertools.ifilterfalse(p, seq):
> return False
> return True
>
>Since the "else" is unnecessary, it disturbs me, I get confused,
>I don't see why it is used (there is no break in the loop) and the
>code becomes much harder to read, for me. OTOH I am sure 99% of
>people would say "look, it is obvious, if elt is in the output
>of ifilter it will return True, else False (viceversa in the
>second case)". But may brain sees that the "else" is unncessary
>and immediately it is disturbed by th redundance.
>Am I the only one? ;)
Well, don't the multiple returns disturb you? I'd suggest this but
probably it's too clever:
from itertools import islice,ifilter
def any(predicate,seq):
return bool(list(islice(ifilter(predicate,seq),1)))
def test():
xs = 'abc123def456'
def fun(x):
print x
return x == '3'
print any(fun,xs)
if __name__=='__main__':
test()
Anton
I also like the any() function suggested above.
def any(p, seq):
"""Returns true if any element in seq satisfies predicate p."""
for elt in itertools.ifilter(p, seq):
return True
return False
In the itertools.imap version does
<True in> test against a continually growing list, ie.
True in [False]
True in [False, False]
True in [False, False, False]
True in [False, False, False, True]
or does it just apply <in> to the next generated element.
Is the itertools.imap version as efficient as the for loop version?
Thanks.
It's used because the for loop is effectively serving as an if
statement. Iterators have no __nonzero__ method -- you can't simply
bool() them. So I use a for loop like a if statement, and throw the
else in there to emphasize that usage. The for loop will never
iterate; either its body executes or it doesn't.
An alternative way to code this would be:
def any(p, seq):
try:
itertools.ifilter(p, seq).next()
return True
except StopIteration:
return False
but I find that less clear.
I also use else because it puts my return statements at the same level
of indentation, which I find more readable, since logically they're
equivalent.
> Am I the only one? ;)
One can only hope! <wink>
Jeremy