Using and and or operator with Python strings
Suppose you are using the value of parameter
, but if the value is say None
, then you would rather like to have an empty string ""
instead of None
. What would you do in general?
if parameter:
# use parameter (well your expression using `" " + parameter` in this case
else:
# use ""
This is what that expression is doing. First you should understand what and
and or
operator does:a and b
returnsb
if a isTrue
, else returnsa
.a or b
returnsa
if a isTrue
, else returnsb
.
parameter and (" " + parameter) or ""
which is effectively equivalent to:(parameter and (" " + parameter)) or ""
# A1 A2 B
# A or B
How the expression is evaluated if:parameter - A1
is evaluated toTrue
:result = (True and " " + parameter) or ""
result = (" " + parameter) or ""
result = " " + parameterparameter - A1
isNone
:result = (None and " " + parameter) or ""
result = None or ""
result = ""
As a general suggestion, it's better and more readable to use
A if C else B
form expression for conditional expression. So, you should better use:" " + parameter if parameter else ""
instead of the given expression. See PEP 308 - Conditional Expression for motivation behind the if-else
expression. How to compare strings with logical operators to a list of strings?
Despite being valid Python code, what you've written is semantically very far away from what you're trying to achieve. This is due to some incorrect assumptions about how the language behaves, or can be made to behave.
First of all, your "list of logical operators" looks and behaves nothing like what you're expecting. This:
["abc" or "def" and "ghi"]
Is a list literal, which will evaluate to a list containing a single string item thanks to short-circuit evaluation:["abc"]
The expression "abc" or "def" and "ghi"
will evaluate down to a single object, in this case "abc"
. Non-empty strings are considered "truthy", and the binary or
operator only needs one of its operands to be true/truthy in order for the whole expression to evaluate as true/truthy.Second, this:
if "abd" and "def" in a:
Must be parsed as:if ("abd") and ("def" in a):
Again, when evaluated as a distinct boolean-expression, the string "abd"
is non-empty, and therefore truthy. This is similar to saying:if True and "def" in a:
or simply:if "def" in a:
There are different ways to solve the issue, but perhaps the simplest solution you're looking for is:if ("abc" in a) or ("def" in a and "ghi" in a):
Just because the code you've written reads like an English sentence to you, doesn't mean that this is how Python will interpret it. Python: Compare strings with 'or' operator
When treated as boolean, an empty string will return False
and a non empty string will return True
.
Since Python supports short circuiting, in the expression a or b
, b
won't be evaluated if a
is True.
In your example, we have '' or 'Trondheim' or 'Hammer Dance'
.
This expression is evaluated from left to right, so the first thing being evaluated is '' or 'Trondheim'
, or in other words False or True
, which returns True
. Next, Python tries to evaluate 'Trondheim' or 'Hammer Dance'
which in turn becomes True or 'Hammer Dance'
. Because of the short circuiting mentioned earlier, because the left object is True, 'Hammer Dance'
doesn't even gets evaluated to True
, which is why 'Trondheim'
is returned.
How to use character or string as operator placed in between operands?
You could do something like this:
import operator
operations = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.truediv}
char = raw_input('enter your operator:')
a = 1
b = 5
c = operations[char](a, b)
print c
Output (for char = +)6
Logical operators in python strings
('browser' or 'chrome')
evaluates to 'browser'
.
See How do “and” and “or” act with non-boolean values?
You can use the any
function:
if any(x in 'start chrome' for x in ('browser', 'chrome')):
# at least one of the words is in the string
and the all
function:if all(x in 'start chrome' for x in ('browser', 'chrome')):
# both words are in the string
and' operator in string.contains
No you have to create 2 conditions and use &
and wrap parentheses around the conditions due to operator precedence:
(df['column_name'].str.contains('test1')) & (df['column_name'].str.contains('test2))
If you wanted to test for either word then the following would work:df['column_name'].str.contains('test1|test2')
python is operator behaviour with string
One important thing about this behavior is that Python caches some, mostly, short strings (usually less than 20 characters but not for every combination of them) so that they become quickly accessible. One important reason for that is that strings are widely used in Python's source code and it's an internal optimization to cache some special sorts of strings. Dictionaries are one of the generally used data structures in Python's source code that are used for preserving the variables, attributes, and namespaces in general, plus for some other purposes, and they all use strings as the object names. This is to say that every time you try to access an object attribute or have access to a variable (local or global) there's a dictionary lookup firing up internally.
Now, the reason that you got such bizarre behavior is that Python (CPython implementation) treats differently with strings in terms of interning. In Python's source code, there is a intern_string_constants function that gives strings the validation to be interned which you can check for more details. Or check this comprehensive article http://guilload.com/python-string-interning/.
It's also noteworthy that Python has an intern()
function in the sys
module that you can use to intern strings manually.
In [52]: b = sys.intern('a,,')
In [53]: c = sys.intern('a,,')
In [54]: b is c
Out[54]: True
You can use this function either when you want to fasten the dictionary lookups or when you're ought to use a particular string object frequently in your code.Another point that you should not confuse with string interning is that when you do a == b
, you're creating two references to the same object which is obvious for those keywords to have the same id
.
Regarding punctuations, it seems that if they are one character they get interned if their length is more than one. If the length is more than one they won't get cached. As mentioned in the comments, one reason for that might be because it's less likely for keywords and dictionary keys to have punctuations in them.
In [28]: a = ','
In [29]: ',' is a
Out[29]: True
In [30]: a = 'abc,'
In [31]: 'abc,' is a
Out[31]: False
In [34]: a = ',,'
In [35]: ',,' is a
Out[35]: False
# Or
In [36]: a = '^'
In [37]: '^' is a
Out[37]: True
In [38]: a = '^%'
In [39]: '^%' is a
Out[39]: False
But still, these are just some speculations that you cannot rely on in your code. How does boolean operator work on string in python
Python and and or operations stop when the answer is determined and return the value of the last object scanned. They do not return True or False. I love this feature and find myself using it all the time.
Since non-empty strings count as True
True and "asdf" or absolutely_anything_here_or_following
stops calculating when it hits the or because the answer is now determined (one of the or values is true), and returns the last thing it checked ("asdf"). No further operands are even inspected.On the other hand, when
False and "asdf" or absolutely_anything_here
hits the or, it doesn't know the anwser yet so continues to the next operand. As long as absolutely_anything_here is the last operation, the answer is determined and the last thing scanned is returned. Python: Using AND and OR with .FIND() method
Expression 'a' or 'z'
always yields 'a'
. Expression 'a' and 'z'
always yields 'z'
. It's not some kind of DSL for making queries into containers, it's a simple boolean expression (and find
is called with its result). If you want to say "is there 'a' or 'z' in the string", you need to do
var1.find('a') != -1 or var.find('z') != -1
And for the second one (both 'a' and 'z' in the string):var1.find('a') != -1 and var.find('z') != -1
Related Topics
How to Change Data Points Color Based on Some Variable
What's the Difference Between Subprocess Popen and Call (How to Use Them)
Does Python Do Slice-By-Reference on Strings
Broken References in Virtualenvs
How to Plot Empirical Cdf (Ecdf)
Get the String Within Brackets in Python
In Python, Is It Better to Use List Comprehensions or For-Each Loops
How to Find the Min/Max Value of a Common Key in a List of Dicts
Convert Categorical Data in Pandas Dataframe
Python, Default Keyword Arguments After Variable Length Positional Arguments
String with 'F' Prefix in Python-3.6
Turning Off Logging in Selenium (From Python)
How to Use the Optional Type Hint
Python Argparse: Default Value or Specified Value
Hide Chromedriver Console in Python