Why does Python show the whole array?

G

Gilles Ganault

Hello

I'd like to go through a list of e-mail addresses, and extract those
that belong to well-known ISP's. For some reason I can't figure out,
Python shows the whole list instead of just e-mails that match:

======= script
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

Any idea why I'm also getting "yahoo.com"?

Thank you.
 
P

Peter Otten

Gilles said:
I'd like to go through a list of e-mail addresses, and extract those
that belong to well-known ISP's. For some reason I can't figure out,
Python shows the whole list instead of just e-mails that match:

======= script
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
        if test.find(item):
                print item
======= output
gmail.com
yahoo.com
=======

Any idea why I'm also getting "yahoo.com"?

Because str.find() returns the position of the search string if found and -1
if it is not found:
-1

Use

if test.find(item) != -1: ...

or

if item in test: ...

to make your example work.

Peter
 
U

Ulrich Eckhardt

Gilles said:
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

Any idea why I'm also getting "yahoo.com"?

find() returns the index where it is found or -1 if it is not found. Both an
index>0 or a -1 evaluate to True when used as conditional expression.

Uli
 
A

Albert Hopkins

Gilles said:
I'd like to go through a list of e-mail addresses, and extract those
that belong to well-known ISP's. For some reason I can't figure out,
Python shows the whole list instead of just e-mails that match:

======= script
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

Any idea why I'm also getting "yahoo.com"?

Because str.find() returns the position of the search string if found and -1
if it is not found:
-1

Use

if test.find(item) != -1: ...

or

if item in test: ...

to make your example work.

Or you could also use the .endswith() method

if test[test.find('@')+1:].endswith(item):
 
D

Dave Angel

Gilles said:
Hello

I'd like to go through a list of e-mail addresses, and extract those
that belong to well-known ISP's. For some reason I can't figure out,
Python shows the whole list instead of just e-mails that match:

======= script
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

Any idea why I'm also getting "yahoo.com"?

Thank you.
Look up the definition of string.find(). It returns a -1 for failure,
not 0. So your test should presumably be
if test.find(item) != -1:
 
G

Gilles Ganault

find() returns the index where it is found or -1 if it is not found. Both an
index>0 or a -1 evaluate to True when used as conditional expression.

Thanks everyone. I shouldn't have assumed that "if test.find(item):"
was necessarily enough to mean True.

for item in isp:
#GOOD if item in test:
if test.find(item) > 0:
print test
 
L

Lawrence D'Oliveiro

Gilles Ganault said:
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

This is why conditional constructs should not accept any values other than
True and False.
 
P

Peter Otten

Lawrence said:
Gilles Ganault said:
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

This is why conditional constructs should not accept any values other than
True and False.

So you think

if test.find(item) == True: ...

would have been better?
 
M

Miles

So you think

if test.find(item) == True: ...

would have been better?

Clearly, any comparison with a boolean literal should be illegal. ;)

-Miles

P.S. ... really, though.
 
J

John Machin

Gilles Ganault said:
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

This is why conditional constructs should not accept any values other than
True and False.

An alternative viewpoint: This is what happens when one user doesn't
understand a long-standing idiom and/or doesn't read the manual.
That's all. It doesn't constitute evidence that such a restriction
would be generally beneficial.
 
N

Niklas Norrthon

Clearly, any comparison with a boolean literal should be illegal.  ;)

So you think

truth_value = True
if test.find(item) == truth_value: ...

would have been better? :)
(couldn't resist...)

/Niklas Norrthon
 
S

Steven D'Aprano

This is why conditional constructs should not accept any values other
than True and False.

I once tried this:

for i in alist.sort():

and got an error I didn't understand because I failed to read the docs.
Clearly for loops shouldn't take sequences but only an integer count,
because that would have prevented my error.
 
L

Lawrence D'Oliveiro

In message <7e7a386f-d336-4186-822d-
An alternative viewpoint: This is what happens when one user doesn't
understand a long-standing idiom and/or doesn't read the manual.
That's all. It doesn't constitute evidence that such a restriction
would be generally beneficial.

Fine if it only happened once. But it's a commonly-made mistake. At some
point you have to conclude that not all those people are stupid, there
really is something wrong with the design.
 
T

Terry Reedy

Lawrence said:
Gilles Ganault said:
test = "(e-mail address removed)"
isp = ["gmail.com", "yahoo.com"]
for item in isp:
if test.find(item):
print item
======= output
gmail.com
yahoo.com
=======

This is why conditional constructs should not accept any values other than
True and False.

Nonesense. Just use 'if item in test:' which tells you all the info you
are using. str.find returns an index that you ignore, so don't use it.
 
J

John Posner

Lawrence said:
> Fine if it only happened once. But it's a commonly-made mistake. At some
> point you have to conclude that not all those people are stupid, there
> really is something wrong with the design.

I think "something wrong with the design" is overstating the case a bit,
and is likely to elicit some negative reactions in this forum. But I
agree with your point, to this extent: this situation illustrates the
way in which Python "overloads" the number zero:

Realm A: "0" indicates the first position in a sequence
Realm B: "0" indicates the Boolean value "False"

You just need to remember that the find() function works in Realm A, and
the "in" operator works in Realm B.

Q: Has anyone on the python-dev list ever proposed a "string"-module
function that does the job of the "in" operator? Maybe this:

if test.contains(item) # would return a Boolean value
 
J

John Machin

Lawrence D'Oliveiro wrote:

 > Fine if it only happened once. But it's a commonly-made mistake. At some
 > point you have to conclude that not all those people are stupid, there
 > really is something wrong with the design.

I think "something wrong with the design" is overstating the case a bit,
and is likely to elicit some negative reactions in this forum. But I
agree with your point, to this extent: this situation illustrates the
way in which Python "overloads" the number zero:

  Realm A:  "0" indicates the first position in a sequence
  Realm B:   "0" indicates the Boolean value "False"

You just need to remember that the find() function works in Realm A, and
the "in" operator works in Realm B.

Q: Has anyone on the python-dev list ever proposed a "string"-module
function that does the job of the "in" operator? Maybe this:

  if test.contains(item)     # would return a Boolean value

Yes.

command_prompt> \python23\python -c "print 'frobozz'.__contains_
_('obo')"
True

Was first introduced in Python 2.2, with only a single character
allowed in the arg.
 
T

Tim Rowe

2009/4/9 Miles said:
Clearly, any comparison with a boolean literal should be illegal.  ;)

Hey, we could have strict type checking at compile time of /all/
operations, couldn't we? Anybody care to join me over at the Ada list?
;-)
 
H

Hrvoje Niksic

John Posner said:
Q: Has anyone on the python-dev list ever proposed a "string"-module
function that does the job of the "in" operator? Maybe this:

if test.contains(item) # would return a Boolean value

That's a string method, not a function in the string module. If you
want a function, use operator.contains:
True
 
J

John Posner

Hrvoje said:
> if test.contains(item) # would return a Boolean value
>

Oops, of course.

That's pretty good, and IMHO a bit better than John Machin's suggestion
to use the __contains__() method. (I have this prejudice that using the
__XXX__ methods in "everyday code" is cheating.)

Given how common string maniuplations are, I guess I'm surprised that
Python hasn't yet made "contains()" into both a "string"-module function
*and* a string-object method.
 
P

Peter Otten

John said:
Given how common string maniuplations are, I guess I'm surprised that
Python hasn't yet made "contains()" into both a "string"-module function
*and* a string-object method.

Could you explain why you prefer 'contains(belly, beer)'
or 'belly.contains(beer)' over 'beer in belly'? The last form may be a bit
harder to find in the documentation, but once a newbie has learned about it
he'll find it easy to remember.

Peter
 

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
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top