Chris St Pierre
Chris St Pierre

Reputation: 350

Strange python syntax, or in print statement

I can't find anything about this, so I'm forced to ask here. I'm sure it's an easy question for anybody who knows python well.

python 2:

print raw_input() == 0 or hash(tuple(map(int, raw_input().split(' '))))

python 3:

print(input()==0 or hash(tuple(map(int,input().strip().split()))))

I am trying to understand why an 'or' is in a print statement. The code in question has a boolean operator inside a print statement, comparing a boolean and an int. This is what I need explained to me. It is obviously specific to python. What would the code print in the case that input()==0 returns true? How can we compare a boolean and a hash, and again, what are we doing making boolean comparisons inside a print statement?

Upvotes: 1

Views: 1103

Answers (3)

TigerhawkT3
TigerhawkT3

Reputation: 49330

In Python, comparisons with or or and make use of two features:

  1. Truthy and falsey values, and
  2. Short-circuiting.

So, when you have something like this:

print(input()==0 or hash(tuple(map(int,input().strip().split()))))

It'll follow the order of operations, checking whether input() returns a 0. Since it's that or the next term, if it's true then the next term has no impact on the result and won't be evaluated. If that happens, it'll print True, since that's what's returned by input()==0.

If that's false, it'll evaluate the next part, getting input, mapping it as an integer, turning it into a tuple, and hashing it. It'll then return that hash whether or not it's a truthy value (a number other than 0, a sequence or set with contents, etc.).

Upvotes: 2

o11c
o11c

Reputation: 16126

I am guessing that your code is Python3, since otherwise it is unlikely that the result of input() would have a strip method.

Here is a long form of the code, with explanations.

# Read a line of input. Returns a string.
a = input()
# Compare to integer 0, always False.
# Effectively, this ignores the first line of input.
b = a == 0
# Separate function to represent lazy evaluation.
def y():
    # Get a second line of input, as a string.
    c = input()
    # Strip leading and trailing whitespace, still a string.
    # This line is useless since split() with no argument does this.
    d = c.strip()
    # Split the line by any runs of whitespace. Returns a list of strings.
    e = d.split()
    # For each string in the list, convert it to an integer in base 10.
    # Return an iterator (not list) of ints.
    # Most people would write (int(s) for x in e) for a generator
    # comprehension, or [int(s) for x in e] for a list comprehension.
    m = map(int, e)
    # Consume the iterator into a tuple of ints.
    # Note that it can't be a list, because lists aren't hashable.
    t = tuple(m)
    # Hash the tuple, returning a single int.
    return hash(t)
# If b is truthy, set x to it. Otherwise, evaluate y() and set x to that.
# Unlike many languages, the arguments to or are *not* coerced to bool.
# Since b is False, y() will be evaluated.
x = b or y()
# Print the result of y().
# i.e. the hash of the tuple of ints on the second line.
# This is essentially a meaningless number.
print(x)

Upvotes: 0

SuperBiasedMan
SuperBiasedMan

Reputation: 9969

Python will first evaluate whether or not input()==0 is True. If it is, then Python will print it and ignore the rest of the line. If the input is not equal to 0 and this evaluates as False, then it will be ignored and the rest of the line will be printed regardless of how it evaluates. So even if the rest of the line would evaluate as False, Python will print its result.

A clearer example would be setting the name of something based on user input and requiring a default value.

name = raw_input("What is your name?")
print ("So your name is...")
print (name or "John Smith")

name will be evaluated as True or False. Since an empty string will be considered False, if the user enters nothing then instead Python will print the default name after the or operator.

Upvotes: 1

Related Questions