Python - function to do string comparison - python

def name(x):
return x==('Jenson'or'Amra'or'McCay'or'Spinner'or'Jones')
print(name('Jenson'))
print(name('McCay'))
This is the question:
"Write a function that takes as input a name of a person (e.g.,
“smith”, “jones”, etc.) This function should check to see if the name
is one of the five names of people on the board. The five names are:
“Jenson”,”Amra”, “McCay”,”Spinner”, and “Jones”. If the name input
into the function is one of those five names, the function should
return the Boolean value True, and if it isn’t, the function should
return False. (remember comments with input types, description, and
test cases) Test the function to make sure it works."
It works if I am doing Jenson but it comes out with false if I put in any other name.

Try like this,
def name(x):
return x in ('Jenson', 'Amra' ,'McCay', 'Spinner','Jones')

How about the "long" way:
def check_name(x):
names_to_check = ('Jenson','Amra','McCay','Spinner','Jones')
for i in names_to_check:
if i == x:
return True
return False
Here is what is happening in your code:
x = 'Jenson', since this is what you have passed in.
This line x == ('Jenson' or 'Amra' or 'McCay' or 'Jones') is actually a boolean operation, and the result of it is always Jenson.
Boolean operations check truth values, and a non-empty string in Python is always True. So actually what ('Jenson' or 'Amra' or 'McCay' or 'Jones') is saying is:
"Either Jenson or Amra or McCay or Jones which ever one is True, set the value to that".
Since Jenson is the first item, and its True (that is, its not an empty string), the entire expression is equal to Jenson (which is why it only works when you pass in Jenson).
A simple example:
>>> ('a' or 'b' or 'c')
'a'
>>> ('b' or 'a' or 'c')
'b'
>>> ('' or '' or 'a')
'a'
>>> (0 or 0 or 1)
1
>>> (False or False or True)
True
The last three illustrate the same comparison. I am checking two empty strings and 'a'. Since an empty string is False in Python, the only thing that is "True" is 'a', which is what is returned, just as if I was comparing 0 with 1.

The syntax x==('Jenson' or 'Amra' or 'McCay' or 'Spinner'or'Jones') is wrong.
It should be like Adem says. or maybe
def name(x):
return x=='Jenson' or x== 'Amra' or x == 'McCay' or x == 'Spinner' or x == 'Jones'

I imagine what is happening is that ('Jenson'or'Amra'or'McCay'or'Spinner'or'Jones') is being evaluated first, and is evaluated to 'Jenson'. That is computed before x is even considered because it is in parentheses. Then x is checked for equality against Jenson. You need to either use a more advanced syntax like x in... as in Adem's answer, or else use return x == 'Jenson' or x == 'Amra' or x == 'McCay'... so that each comparison is run one after another.

Related

Disjunction and membership in python [duplicate]

This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
Closed last year.
When I try this code:
a = ['b']
if 'i' or 'j' in a:
print('Yes!')
else:
print('No!')
The output is 'Yes!'. Flake8 and python do not complain about an error or bad form.
What exactly happens when the code runs? Why does 'i' or 'j' in a evaluate as true?
The problem is that in the statement i evaluates to True, which means that the statement is then: True or 'j' in a. This is always true and your result will be always 'Yes!'.
You can use something like this to check if one of the values is in your list:
a = ['b']
chars_to_check = ['i', 'j']
filtered_list = [i for i in a if i in chars_to_check]
if len(filtered_list)>0:
print('Yes!')
else:
print('No!')
The example is from this question, where people also posted more efficient or shorter solutions to your problem. The solution I like the most would be this one:
a = ['b']
if {'i','j'} & set(a):
print('Yes!')
else:
print('No!')
EDIT: I think now I understand the question.
First of all python sees that you have a or in your if statement. This means the first expression (in your case 'i') is evaluated first. If the first expression is True, the whole statement is True and the second expression is not even evaluated. The evaluation order of or is explained here for example.
Now to why the first expression is always True. Python automatically evaluates all objects not only boolean values. For this the objects can for example contain a function __bool__() that gives back the boolean value of an object. The object in your case is a single character 'i', which evaluates to True. The reason is that it is defined that the boolean value of a string is always True except for the empty string (''). Here you can see an example of the evaluation:
print(bool('i')) # True
print(bool('')) # False
An answer that shows which objects are considered False and which are considered True can you find here.

Why is "is None" ok, but "is True" is not? [duplicate]

Apologies if this has been asked before, but I have searched in vain for an answer to my exact question. Basically, with Python 2.7, I have a program running a series of geoprocessing tools, depended on what is reqested via a series of True/False variables that the user adjusts in the script e.g.
x = True
if x:
run function
However, I have now discovered that x does not need to be literally "True" for the function to run. For example:
In: x = True
if x:
print True
Out: True
In: x = 123
if x:
print True
Out: True
In: x = 'False'
if x:
print True
Out: True
In: x = False
if x:
print True
Out:
So any value other than False appears to evaluate to True, which would not be the case for if x == True or if x is True. Seeing as PEP 8 strongly recommends only using the if x: variant, can anybody explain why this behaviour occurs? It seems that if x: is more a test for "if x is not False" or "if x exists". With that in mind, I believe I should be using if x is True: in this case, despite what PEP 8 has to say.
The following values in Python are false in the context of if and other logical contexts:
False
None
numeric values equal to 0, such as 0, 0.0, -0.0
empty strings: '' and u''
empty containers (such as lists, tuples and dictionaries)
anything that implements __bool__ (in Python3) to return False, or __nonzero__ (in Python2) to return False or 0.
anything that doesn't implement __bool__ (in Python3) or __nonzero__ (in Python2), but does implement __len__ to return a value equal to 0
An object is considered "false" if any of those applies, and "true" otherwise, regardless of whether it's actually equal to or identical with False or True
Now, if you've arranged that x is necessarily one of the objects True or False, then you can safely write if x. If you've arranged that the "trueness" of x indicates whether or not to perform the operation, regardless of type, then you can safely write if x. Where you can write that you should prefer to do so, since it's cleaner to read.
Normally, if it is allowed for x to take the value True then you're in one of those two cases, and so you would not write if x is True. The important thing is to correctly document the meaning of x, so that it reflects the test used in the code.
Python programmers are expected to know what's considered true, so if you just document, "runs the function if x is true", then that expresses what your original code does. Documenting it, "runs the function if x is True" would have a different meaning, and is less commonly used precisely because of the style rule in PEP8 that says to test for trueness rather than the specific value True.
However, if you wanted the code to behave differently in the case where x is an empty container from the case where it is None, then you would write something like if x is not None.
I'd like to add a short example where those 3 tests differ:
def test(x):
print(x, ":", bool(x), x == True, x is True)
test("something")
test(1)
test(True)
The output (pretty formatted):
# "something" : True False False
# 1 : True True False
# True : True True True
x = 'False'
x = 123
Are both True
Other truth values.
The document explains other values.
As far as the PEP8 reason, its far more semantic to read if this_file_is_green
Other falsey values include 0, '', []. You should just use the if x: version.
It goes without saying that you should write code that does what you need. But in most cases, you simply don't need to say == True or is True, because you don't need to distinguish True from other "truthy" values. So it's recommended to leave that out for simplicity.
The case where you definitely should use == True or is True is when you do need to distinguish True from other truthy values.
In your example, do you care about the difference between True and 123? That would tell you which way to code it.
One thing about coding == True or is True: it will raise a minor red flag when other developers read your code. They won't think it's wrong, they will just wonder why it's there and will want to know why it's important to treat True differently from other truthy values in this particular case.
In other words, if you don't need it, it's best not to use it.
The ability to say
if x:
...
is considered a feature. You can also specify when the test should be considered to pass or not for user defined classes (just define the method __nonzero__ in Python 2.x or __bool__ in Python 3).
For example for strings and containers like lists, dictionaries or sets the test if x ... means "if x is not empty".
Note that the rationale is not that this allows less code to write, but that resulting code is easier to read and to understand.
If you like instead to write if x is True ... have you considered to go farther down that path to if (x is True) is True ... or if ((x is True) is True) is True ... ? :-)
In Python 2.7, if a: and if a==True are not giving the same output for values different to 1. Here are some snippets of code to demonstrate the different behaviors:
with a=1
a=1
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (1,True)
a=1
if a:
print (a,"True")
else:
print (a,"Not True")
output> (1, True)
with a=2
a=2
if a:
print (a,"True")
else:
print (a,"Not True")
output> (2, True)
a=2
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (2, Not True)
if you use if x ,it means it has to evaluate x for its truth value.But when you use x ==True or x is True.It means checking whether type(x)==bool and whether x is True.
attention : x is True is no equal to bool(x)==True
when you use x is True , you are checking the id of x and True.

'if' not followed by conditional statement

I'm going through Zed's "Learn Python The Hard Way" and I'm on ex49. I'm quite confused by the following code he gives:
def peek(word_list):
if word_list: # this gives me trouble
word = word_list[0]
return word[0]
else:
return None
The condition of the if statement is giving me trouble, as commented. I'm not sure what this means as word_list is an object, not a conditional statement. How can word_list, just by itself, follow if?
The if statement applies the built-in bool() function to the expression which follows. In your case, the code-block inside the if statement only runs if bool(word_list) is True.
Different objects in Python evaluate to either True or False in a Boolean context. These objects are considered to be 'Truthy' or 'Falsy'. For example:
In [180]: bool('abc')
Out[180]: True
In [181]: bool('')
Out[181]: False
In [182]: bool([1, 2, 4])
Out[182]: True
In [183]: bool([])
Out[183]: False
In [184]: bool(None)
Out[184]: False
The above are examples of the fact that:
strings of length >= 1 are Truthy.
empty strings are Falsy.
lists of length >= 1 are Truthy.
empty lists are Falsy.
None is Falsy.
So: if word_list will evaluate to True if it is a non-empty list. However, if it is an empty list or None it will evaluate to False.
He is checking if word_list is empty or not. If a list is empty and it is used in a conditional statement, it is evaluated to False. Otherwise, it is evaluated to True.
word_list = ['some value']
if word_list:
# list is not empty do some stuff
print "I WILL PRINT"
word_list = []
if word_list:
# list is empty
print "I WILL NOT PRINT"
In the above code, only the first snippet will print.
See the following reference: https://docs.python.org/2/library/stdtypes.html#truth-value-testing
word_list is a list and when you use it for an if statement condition you check word_list is empty or not :
word_list = []
bool(word_list) # False
if word_list :
print "I'm not empty" # would not printed
word_list = ['a']
bool(word_list) # True
if word_list :
print word_list[0] # 'a'
as Mad Physicist said even None elements in a list means that it's not empty:
word_list = [None]
bool(word_list) # True
What is required for an if block is just something that can be evaluated either to True or to False. A conditional evaluates directly to one of those, but there are other objects that can be converted. To see what any given object is, you can use bool:
>>> mylist = []
>>> bool(mylist)
False
>>> mylist = [4, 3, 6]
>>> bool(mylist)
True
You see, a list is False if it is empty, but True otherwise. Therefore, the if word_list: block will be evaluated if word_list is nonempty. Strings also are False if they are empty, but True otherwise. Same thing with tuples, dictionaries, sets. With numbers, 0 and 0.0 are False, but any other number is True. A fairly common argument to give to indicate to the function to come up with its own value is None which evaluates to False, so the if not mylist: block will be executed if mylist is empty or if mylist is None. (It would also be executed if mylist is 0, (), {}, etc.; but it's unlikely that mylist would be given those)
Take a look at this docs page for Truth Value Testing in python. You should get clear idea about your situation after reading this. Here is the relevant part for easy access.
5.1. Truth Value Testing
Any object can be tested for truth value, for use in an if or while
condition or as operand of the Boolean operations below. The following
values are considered false:
None
False
zero of any numeric type, for example, 0, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a __bool__()
or __len__() method, when that method returns the integer zero or bool
value False.
All other values are considered true — so objects of many types are always true.
Read the first sentence (bolded) again, and note the bolded parts in the fourth rule. This relates to your question.
So, according to the 4th rule, if your word_list is empty, the condition evaluates to False, otherwise it evaluates to True.
I know you trust in the docs, but here is a code snippet to actually test the truth values for yourself. (I know it is needless to do something like this, but I am always tempted to see things with my own eyes)
def test_truth_value(arg):
# ANY object can be evaluated for truth or false in python
if arg: # or to be more verbose "if arg is True"
print("'{}' is True".format(arg))
else:
print("'{}' is False".format(arg))
class dummy_length_zero():
def __len__(self):
return 0
def __str__(self):
return 'instance of class: "dummy_length_zero"'
class dummy_bool_False():
def __bool__(self):
return False
def __str__(self):
return 'instance of class: "dummy_bool_False"'
obj_dummy_0 = dummy_length_zero()
obj_dummy_false = dummy_bool_False()
args = [None, False, 0, 0.0, 0j, '', (), [], {}, obj_dummy_0, obj_dummy_false]
for arg in args:
test_truth_value(arg)
And lastly, to test that last statement so objects of many types are always true, just remove the implementation of __len__() or __bool__() method from dummy_length_zero or dummy_bool_False class respectively, and check for truth.
In python, everything has an implicit boolean value. Putting any object in an if statement directly is equivalent (but more Pythonic than) doing if bool(word_list):. None, empty sequences, empty sets, empty dicts, 0, False, 0.0 all evaluate to False. Most other objects evaluate to True. That makes if word_list: the most Pythonic way of ensuring that the list is not None or empty before accessing the first element. The long way of expressing the same thing would be if word_list is not None and len(word_list) > 0:.
In Python, every expression can be evaluated to a boolean value (i.e. either True or False).
The following, basic, expressions evaluate to False
The keyword False (obviously!)
The keyword None
The number 0 (0, 0.0 ... )
empty sequence (tuple, list, string)
empty mapping (dictionary)
All other expressions evaluate to True.
So, what the if statement does is evaluating the expression that follows the if keyword to either True or False, then act accordingly.
So in your specific example, if word_list matches any of the above cases it will be considered False, otherwise, it will be considered True.
[#] reference

how to use python's any

I feel very confused about some code like this[not written by me]:
version = any(func1(), func2()) # wrong, should be any([func1(), func2()])
def func1():
if something:
return 1
else:
return None
def func2():
if something:
return 2
else:
return 3
version must be a num. when [func1(), func2()] is [1, None], should return 1, when is [None, 2], should return 2, when [1, 2], should return 1.
so I think it's wrong to use any() in this code, because any() just return True or False. If I rewirte this logic using another way, I can not find a graceful way as a pythoner.
I want to know whether any() can achieve the logic, if not, how to achieve it gracefully?
You can simply use or here.
version = func1() or func2()
Make sure the functions are defined before trying to call them.
This works because or returns the first True-like value or the last value (if no value is True-like) . And 'None' is considered False-like in Boolean context.
#AnandSKumar's answer is optimal. But just to give you some information on any if you are interested:
Take this example:
>>> def foo():
... return 2
...
>>> def boo():
... return 3
...
>>> def doo():
... return 4
...
>>> f = [foo, boo, doo]
>>> any(i() < 3 for i in f)
True
Ultimately what is happening inside the any is, iterate over the array of methods j, and indicate whether each item is less than 3, what the "any" will do in this case is return "ANY" condition that matches that. So even if you find one that is False, it will still return True.
There is another similar method to this called "all", that will ensure that ALL conditions are met based on your condition you are checking. Here is the example:
>>> all(i() < 3 for i in f)
False
So, as you can see, because one condition failed, it will return False.
For the arbitrary length case (where explicitly chaining or doesn't make sense), you can make a version of any that returns the first truthy value or a given value when all results are falsy with:
# If on Py2, you'll want to do this to get shortcircuiting behavior
from future_builtins import filter
result = next(filter(None, iterable_to_check), False) # False can be replaced with a chosen default
The filter only produces "truthy" values, and the two arg next gets the first "truthy" value, or the default value if filter finds no "truthy" values.
If the iterable_to_check is a non-empty Sequence (rather than merely Iterable), you can exactly match the behavior of chained ors (the "falsy" result is the last value, not a specific value like False or None) with:
result = next(filter(None, sequence_to_check), sequence_to_check[-1])
to use the final element ("truthy" or "falsy") as the result when all elements were "falsy".
To be clear, if the set of things to test is fixed and smallish, explicit or per Anand's answer is the better way to go.

How do boolean operations work with parentheses in python 2.7?

Found this little oddity while playing around.
>>> 'Hello' == ('Hello' or 'World')
True
>>> 'Hello' == ('World' or 'Hello')
False
>>> 'Hello' == ('Hello' and 'World')
False
>>> 'Hello' == ('World' and 'Hello')
True
Is there some trick to this logic that I'm not getting? Why is the order of the strings the determining factor of these queries? Should I not be using parentheses at all? Why does changing to "and" flip the outputs?
Thanks a buncharooni.
In Python, all objects may be considered "truthy" or "falsy". Python uses this fact to create a sneaky shortcut when evaluating boolean logic. If it encounters a value that would allow the logic to "short-circuit", such as a True at the beginning of an or, or a False at the start of an and, it simply returns the definitive value. This works because that value itself evaluates appropriately to be truthy or falsy, and therefore whatever boolean context it's being used in continues to function as expected. In fact, such operations always just return the first value they encounter that allows them to fully evaluate the expression (even if it's the last value).
# "short-circuit" behavior
>>> 2 or 0
2
>>> 0 and 2
0
# "normal" (fully-evaluated) behavior
>>> 'cat' and 'dog'
'dog'
>>> 0 or 2
2
x or y returns the first operand if its truthy, otherwise returns
the second operand.
x and y returns the first operand if its
falsey, otherwise returns the second operand.
For what it looks like you're trying to accomplish you may prefer this:
'Hello' in ['Hello', 'World']

Categories

Resources