tags:

views:

172

answers:

6

What statemen should i use for this kind of task:

I need finde if string variable a is in string variable b.

What should I use?

+4  A: 
if a in b:
    # ...found it, do stuff...

or

if b.find(a) != -1:
    # ...found it, do stuff...

The former is probably more pythonic, but the latter lets you catch issues sooner if a or b are not the types you were expecting, since if a or b aren't strings, the latter will always fail non-silently, whereas the former can misbehave silently in some cases (for instance, 'foo' in ['foobar'] or even 'foo' in [1,2,3]).

Amber
Your `'foo' in ['foobar']` example in a comment above works better, because `[1,2,3]` doesn't contain 'foo' in any form.
JAB
Both are forms of failure - the [1,2,3] was just meant to illustrate that you wouldn't really be able to tell if something completely different (a numerical list) was passed in. A more real-world example might be passing in a dict instead of a particular value from that dict.
Amber
b.find(a) returns a -1 if a is not in b, so the second code sample won't work the way you're expecting. See [my answer](http://stackoverflow.com/questions/3259233/if-is-in-statement-python/3259365#3259365).
GreenMatt
Fixed, thanks for the catch GreenMatt (forgot that it returns -1 instead of something like False).
Amber
@Amber: -1 If you forgot that it returns -1, then you can't be using `find` very often in your code. BTW, do you also advocate `d.has_key(k)` in preference to `k in d`?
John Machin
@Amber: `False >= 0` returns `True`. So no, it doesn't fail for False, just for -1.
JAB
+14  A: 

How about

if a in b:
    print "a is in b"

If you also want to ignore capitals:

if a.lower() in b.lower():
    print "a is in b"
Juri Robl
Note that this can lead to silent failures in some cases. (Example: `'foo' in ['foobar']`)
Amber
@Amber: I don't think that's a "silent failure", that's developer error, expecting the same behavior from two different types of objects (lists and strings).
Nicholas Knight
Nicholas: chances are if a list is getting passed to something that is expecting a string, that's not intended - that is, the developer didn't expect the same behavior from both so much as they never expected to receive one or the other at all. It's better to raise an error due to having a different type then expected than it is to just not pass the `if` test.
Amber
(In other words: most things that work with one type of data usually aren't intended to work with another, even if it's *possible* for them to. Usually if they're being passed a type of data other than what they were designed to work on, it's the result of a code error somewhere else that should be discovered and fixed.)
Amber
@Amber: I can appreciate the sentiment, but if developers aren't already ensuring that the documented requirements for e.g. a function parameter are met, their codebase is going to have a _lot_ of problems, some of which are even more subtle. To me, it's just one of the tradeoffs of duck-typing.
Nicholas Knight
But How to ignore capital letters?
Pol
you could try `if a.lower() in b.lower():`
Juri Robl
@Nicholas: I daresay most of the time you don't see a bunch of `if type(param) == 'blah'` checks at the top of functions. Something has to catch stuff, even if it's just in the development phase before things are "stable".
Amber
@Genmutant: Not if you want a case-sensitive check. @Amber: `if isinstance(param, blah):` is better/more useful, because it doesn't return `False` for subclasses. Also the Python documentation recommends `isinstance()` rather than `type()` for checking the types of objects anyway. http://docs.python.org/library/functions.html#type
JAB
+4  A: 
if a in b:
    # insert code here
JAB
+2  A: 

Strings are treated like lists of characters in Python. Therefore, the following will work whether a is a character and b is a string or if a is an element type and b is a list:

if a in b:
    #foo
else:
    #bar

(Internally, Python handles strings and lists differently, but you can treat them as the same thing in many operations, like list comprehensions).

thebackhand
How to ignore capital letters?
Pol
I'm not sure what you mean by 'ignore capital letters'. Do you want it to ignore the case entirely and match "a" if "A" is in the string? One easy way is to convert the strings to lowercase:if a.lower() in b.lower(): #fooelse: #barOr do you want it to match "a" if and only if "a" is in the string? That's easy - by default, Python only matches the exact character, so what I wrote above should work.
thebackhand
+2  A: 

For finding one string in another, you may want to try the string find method.

if b.find(a) != -1:  # -1 will be returned when a is not in b
    do_whatever
GreenMatt
Is it ignore capital letters?
Pol
@Pol: No, it doesn't. You'd have to do something like if b.upper().find(a.upper()) != -1: ...
GreenMatt
Eww! You recommend `b.find(a)!==1` over `a in b` ?!
Nas Banov
GreenMatt
+1  A: 
>>> a = '1324'
>>> b = '58132458495'
>>> if a in b:
      print(True)

>>> True
Zonda333