Using "And" and "Or" Operator with Python Strings

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 returns b if a is True, else returns a.
  • a or b returns a if a is True, else returns b.

So, your expression:

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 to True:

    result = (True and " " + parameter) or ""

    result = (" " + parameter) or ""

    result = " " + parameter
  • parameter - A1 is None:

    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



Leave a reply



Submit