简体   繁体   中英

Python doesn't recognize -1 as False?

I recently wrote a Python program that used:

if s.find('something'): 

or

if s.find('something')==True:

but nothing worked correctly until I used:

if s.find('something') >0

That's the only way I could get an accurate True decision in my program.

It seems -1 result wasn't recognized as False. Successful finds weren't recognized as True either. So looking for -1 (False) or a positive number >0 (True) was the only thing that worked for me.

What was I doing wrong? This can't be the way Python works, can it?

You are interpreting the return value of find incorrectly. The documentation states:

str.find(sub[, start[, end]])

Return the lowest index in the string where substring sub is found, such that sub is contained in the slice s[start:end] . Optional arguments start and end are interpreted as in slice notation. Return -1 if sub is not found.

Of all numbers, Python considers only 0 to be false; -1 is true . As find returns the index of the beginning of the match, and 0 is a valid index to a string, -1 is returned when no match was found.

Thus your code should rather* be:

if s.find('something') != -1: 

or

if s.find('something') >= 0:

Though they're not the most Pythonic either, if you just want to see if s contains 'something' - see below.


Now, about your second example: the bool constant False compares equal to 0 :

>>> 0 == False
True

and bool constant True only equal to number 1 :

>>> 1 == True
True
>>> 2 == True
False

Thus the expression s.find('something') == True would be totally equivalent with s.find('something') == 1 ; and the whole expression would evaluate to True only if the s would be of form xsomethingxxxx , with a match for something starting at the 2nd character (index 1).


The documentation for str.find continues with the following note:

Note

The find() method should be used only if you need to know the position of sub . To check if sub is a substring or not, use the in operator:

 >>> 'Py' in 'Python' True 

Thus the form that is the most Pythonic for the problem in your question is

if 'something' in s:

As suggested by @myaut, if you need the position of 'something' within s and expect it to contain the value, you should use str.index instead, which will throw an exception if the substring was not found within the string.

 try:
     position = s.index('something')
     print("'something' found at", position)
 except ValueError:
     print(s, "does not contain the substring 'something'")

Python thinks 0 is False , not -1 .

As you can see in the Python documentation , Python tries hard to have many different kinds of False values:

  • False
  • None
  • 0 of any numeric type: 0 , 0L , 0.0 , 0j .
  • any empty sequence: '' , () , [] .
  • any empty mapping: {} .

Your intuitive notion that -1 should be False in Python makes some sense, but that is just not how Python was designed. Zeros and empties are falsey in Python.

If you only want to check wether a string is contained in another, use:

if 'something' in s:
    print 'something in %s' % s
else:
    print 'bad luck'

-1 as an error code came from C, but that leads to spaghetti code of checking return values.

Python has more reliable way to report an error: raise an Exception . Ie str.index does that:

>>> 'abcde'.find('cd')
2
>>> 'abcde'.index('cd')
2
>>> 'abcde'.find('zx')
-1
>>> 'abcde'.index('zx')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found

And of course to check if string contains substring you should use in operator:

>>> 'ab' in 'abcde'
True
>>> 'zx' in 'abcde'
False

Speaking of if statements you should note that comparing to boolean is a bad idea (check for example PEP-8 ).

Every type in Python defines its own rules which values are considered "True": Truth value testing

The quickest way to verify what is the bool value of it;

bool(-1)
True

bool(0)
False

bool('')
False

and so on,

You are not doing something wrong.

In python bool inherit from int . False is 0 and True is 1 . You can try int(True) and int(False) . If you try bool(0) you will get False , but if you write bool(-1) or bool(1) you always will get True . If you use find you will get -1 so you need to use >= 0 . You can find 'something' inside 'something else' .

You can write if 'something' in s: . I think that find is deprecated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM