I know it's a basic question but please bear with me. Let's say if we have 4 strings below:
a = ''
b = 'apple'
c = 'orange'
d = 'banana'
So, normally if I want to check if any of the three string a b c is empty, I could use len() function.
if len(a) == 0 or len(b) == 0 or len(c) == 0:
return True
But then I thought it is too troublesome to write like above if I have many strings. So, I used
if not a:
return True
But, when i am checking for multiple strings b c d using the above method, it returns True and I am puzzled as non of the strings b c d where empty.
if not b or c or d:
return True
What is going on?
The problem lies with this line:
if not b or c or d:
You need to include the "not" condition for each string. So:
if not b or not c or not d:
You could also do it like this:
return '' in [a, b, c, d]
The not operator has higher precedence than or.
return not b or not c or not d
should work.
Related
This question already has answers here:
Test if all N variables are different
(4 answers)
Closed 2 years ago.
I have four string variables: a,b,c,d. I can't know their values (they are assigned randomly), and I don't care. I only need to make sure that every single on of them is different from others and there are not two variables with the same value. I tried
if a != b != c != d:
return true
but it doesn't work. What should I do?
You can use the naive approach:
if a != b and a != c and a != d and b != c and b != d and c != d:
# do something
Or you can make use of the fact that a set cannot hold the same hashable value twice:
if len(set([a, b, c, d])) == 4:
# do something
Or, a shorter way of writing the same:
if len({a, b, c, d}) == 4:
# do something
The reason your code doesn't work is because you're really doing this:
if a != b and b != c and c != d:
return true
So, it only checks part of what you need to check, it checks if all of the values directly following each other are equal, but not whether values more than one position apart are equal.
Do this?
assert len({a, b, c, d}) == 4 # set of 4 distinct elements should be 4
if len({a, b, c, d}) == 4:
return True
The reason your conditions don’t work
>>> 1 != 2 != 1
True
From the above example, 1 != 2 and 2 != 1, hence passing the condition. It doesn’t check your first and third variable's equality.
You cannot cannot chain comparisons like this. Below is one way to do it using if statements, although it is messy.
if (a != b and a != c and a != d
and b != c and b != d and c !=d):
return True
A nifty approach (albeit with some minor speed and space costs) is the following:
things_to_see_if_unique = [a, b, c, d]
if len(things_to_see_if_unique) == len(set(things_to_see_if_unique)):
return True
In this answer it is stated that you can use return A+1 if A > B else A-1in python 3, yet when i try to use it:
def max3(a,b,c):
return a if a > b and c
return b if b > c else c
i get an invalid syntax error. I've tried looking online but I can't find anything on this, if anyone could help I'd appreciate it.
thanks.
You can nest the conditional expression:
def max3(a,b,c):
return a if a > b and a > c else b if b > c else c
Just make sure to always have an else part, otherwise the expression won't know what to evaluate to. Whether this is the most readable solution is at best questionable. There is no price for fewest lines/bytes (unless you are playing code golf).
Also note that a > b and c is not the same as a > b and a > c. You can shorten that to b < a > c, but then readability will take another hit.
The second return statement in the function will not have any effect and the function will return whatever is returned by the first return statement.
In the first return statement there must be an else otherwise it will be an syntax error.
So, it should be
return a if a>b else b
To evaluate max in 3 ints
return a if a > b and a > c else b if b > c else c
def max3(a,b,c):
if a > b and a > c:
return a
elif b > c else a > c:
return b
use colons at the end of a conditional statement.
using an "else:" part is not compulsory.
I discovered today that you can use and in variable assignment, similarly to how or is used. I rarely come across using or in this way, but have never even heard of people using and this way. Is this too obscure of a feature to recommend using or are there some concrete use cases where it helps with code clarity or brevity?
a = 1
b = 3
# c is equal to b unless a or b is False; then c is equal to the "False" value. False may be 0, [], False, etc.
c = a and b
print(f'a = {a}, b = {b}, c = {c}')
>>>a = 1, b = 3, c = 3
d = 1
e = 5
# f is equal to d unless d is False; then f is equal to e. Again, "False" may be 0, [], False, etc.
f = d or e
print(f'd = {d}, e = {e}, f = {f}')
>>>d = 1, e = 5, f = 1
There seems to be a weird inconsistency where it's obviously fine to use operators to evaluate a condition and set a variable to the truthiness of that condition (e.g. g = h > i or j = k is l etc).
However, and seems to be an exception. Instead of evaluating the condition right of the assignment, the variable is assigned according to the rule described in the above comment. Why doesn't c = a and b just evaluate to True or False depending on both a and b having truthy values? (The above example would evaluate to True)
Thanks
Short circuiting with and is a convenient way to express your intent with little code (a desirable goal indeed).
Consider this initialization, and what you would have to do if user wasn't known to be non-null.
name = user and user.name
Sure, a ternary would be a similar oneliner
name = user.name if user else None
but is it that readable?
Finally, when chaining multiple getters using the short-circuiting and truly starts to save your sanity.
coords = user and user.location and user.location.coords
Use or to provide a better default instead of None when you know for sure it wouldn't be a problem to override a falsey value.
name = user and user.name or 'Unnamed'
Basically what's going on here as has been stated is Short Circuit Evaluation. When the first value in an and evaluates to True then it returns the second value vice returning the False value. Consider these statements
>>> 1 and 0
0
>>> 1 and 3
3
>>> 0 and 1
0
>>> False and "Text"
False
"Text" and False
False
Your question: Why doesn't c = a and b just evaluate to True or False depending on both a and b having truthy values?
According the the Python manual, the definition of a and b is:
if a is false, then a, else b
So in your particular case when a has no side effects, the above translated into actual Python would be equivalent to:
c = a if not a else b
But it is not generally true that a has no side effects. So the difference between c = a and b and c = a if not a else b is as follows:
With a and b, if a is true then b will never be evaluated and a is evaluated once.
With c = a if not a else b, as before if a is true then b will never be evaluated but a will be evaluated a second time, which could be an issue if a does have side effects.
I have some code that causes Pylint to complain:
The if statement can be replaced with 'var = bool(test)' (simplifiable-if-statement)`
The code (with obfuscated variable names) is below.
A = True
B = 1
C = [1]
D = False
E = False
if A and B in C:
D = True
else:
E = True
print(D, E)
How can this be simplified so that Pylint does not throw any errors?
I don't quite understand how bool() can be used for this. I know it converts any value to a Boolean value, but I don't know how it can be applied here.
That logic can be expressed as:
D = A and B in C
E = not D
Try this:
D = bool(A and B in C)
E = not bool(A and B in C)
I was initially a bit confused by the accepted answer and then realized my problem was not with the accepted answer itself (which is fully correct indeed) but with the specificity of the question. I needed a more generic / simple use case and so I will try to provide one, hoping it will be of help for someone.
The simplifiable-if-statement Pylint refactor basically happens when we use an if-else statement to assign a value to a boolean variable, which could have otherwise been assigned directly, without using the if-else statement at all.
A generic example could be:
if <condition>:
variable = True
else:
variable = False
which can (and should) be simplified as:
variable = <condition>
where <condition> is a boolean expression.
A concrete example:
if a > 5:
b = True
else:
b = False
should be rewritten as
b = a > 5
Getting back to the original question, in this case the condition is A and B in C and, as pointed out by other contributors, the redundant snippet:
D = False
E = False
if A and B in C:
D = True
else:
E = True
should be simplified as
D = A and B in C
E = not D
I am new to python and was wondering if someone could help me out with this. I am trying to see if the elements in b are in a. This is my attempt. Currently I am not getting any output. Any help would be appreciated, thank you!
a = [1]
b = [1,2,3,4,5,6,7]
for each in b:
if each not in a == True:
print(each + "is not in a")
You are testing two different things, and the outcome is False; Python is chaining the operators, effectively testing if (each is in a) and (a == True):
>>> 'a' in ['a'] == True
False
>>> ('a' in ['a']) and (['a'] == True)
False
>>> ('a' in ['a']) == True
True
You never need to test for True on an if statement anyway:
if each not in a:
is enough.
You should be able to just say:
if each not in a:
print ("%d is not in a" % each)
Your actual expression is using operator chaining:
if a > b > c:
parses as:
if (a > b) and (b > c):
in python. which means your expression is actually being parsed as:
if (each not in a) and (a == True):
but a == True will always return False, so that if block will never execute.
a = [1,2,3]
b = [1,2,3,4,5,6,7]
c = [7,8,9]
print set(a) <= set(b) #all elements of a are in b
print set(c) <= set(b) #all elements of c are in b
It is better to see the difference between B and A
set(b).difference(set(a))
You don't need ==True. Just:
if each not in a:
This is really easy using sets:
a = [1]
b = [1, 2]
only_in_b = set(b) - set(a)
# set([2])
Another way:
for bb in b:
try:
a.index(bb)
except:
print 'value is not in the list: ' + str(bb)
I would like to add that if the two lists are large. This is not the best way to do it. Your algorithm is O(n^2). The best way is to traverse a, adding the elements as keys to a dictionary. Afterwards, traverse the second list, checking if the elements are already in the dictionary, this instead is an O(n) algorithm.