1

Is it possible to implement the assignment of a variable to the value of the logical "and" or "or"? and use them in a comparison expression?

logical_obj = bool()

if True:
    logical_odj = or
else:
    logical_obj = and

if 1 + 2 == 3 logical_obj 3 + 1 == 5:
    pass
5
  • This isn't exactly a duplicate of the marked question as operator does not expose functions for and or or. In a pinch bitwise operators could be used, but that would probably justify an answer. Commented Apr 10, 2020 at 0:59
  • 1
    See: stackoverflow.com/questions/7894653/… Commented Apr 10, 2020 at 1:00
  • 2
    1 or 3 == 4 probably isn't what you want anyway, but 1 == 4 or 3 == 4. Commented Apr 10, 2020 at 1:04
  • In that case, you probably want to use any([1 == 4, 3==4]) or all([1==4, 3==4]), as desired. Commented Apr 10, 2020 at 1:05
  • (And you can assign the functions any and all to a variable.) Commented Apr 10, 2020 at 1:13

3 Answers 3

2

and and or are operators, like + and -, and cannot be assigned to variables. Unlike + et al., there are no functions that implement them, due to short-circuting: a and b only evaluates b if a has a truthy value, while foo(a, b) must evaluate both a and b before foo is called.

The closest equivalent would be the any and all functions, each of which returns true as soon as it finds a true or false value, respectively, in its argument.

>>> any([1+2==3, 3+1==5])  # Only needs the first element of the list
True
>>> all([3+1==5, 1+2==3])  # Only needs the first element of the list
False

Since these are ordinary functions, you can bind them to a variable.

if True:
    logical_obj = any
else:
    logical_obj = all

if logical_obj([1 + 2 == 3, 3 + 1 == 5]):
    pass

The list has to be fully evaluated before the function can be called, but if the iterable is lazily generated, you can prevent expressions from being evaluated until necessary:

>>> def values():
...    yield 1 + 2 == 3
...    print("Not reached by any()")
...    yield 3 + 1 == 5
...    print("Not reached by all()")
...
>>> any(values())
True
>>> all(values())
Not reached by any()
False
Sign up to request clarification or add additional context in comments.

Comments

0

No it's not possible as these are operators but you can wrap them to a function which will then be always same:

def logical_op(cond, a, b):
  if cond:
    return a or b
  else:
    return a and b`

if logical_op(True, val1, val2) == expected:
  ...

or depending on your code you can apply De Morgan's law and convert and to or (and vice versa) by negation.

Comments

0

This is a bit of a doozy. One possible analogue replicates the short circuiting by also implementing lazy evaluation. This means the second argument must be converted to a function; a and b would convert into sc_and(a, lambda: b).

def sc_and(value, alternative_function):
  if value:
    return alternative_function()
  else:
    return value

Iterators are Python's native means of performing such lazy evaluation, so you can use the shortcut in any and all using e.g. generator expressions:

t1s = (1, 3)
#     +
t2s = (2, 1)
#     ==
rhs = (3, 5)

any(t1+t2==rh for (t1,t2,rh) in zip(t1s,t2s,rhs))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.