-1

So I was trying to solve an algorithm and while trying to find other solutions to it, I found one which was very short and very fast, just one problem...I can't seem to understand what this line is doing:

Full solution:

def proper_fractions(n):
    phi = n > 1 and n
    print(phi)
    for p in range(2, int(n ** .5) + 1):
        if not n % p:
            phi -= phi // p
            while not n % p:
                n //= p
    if n > 1: phi -= phi // n
    return phi

Line that I don't understand:

phi = n > 1 and n

Please forgive me If it is very easy to understand, I just have never come across something like this, I've only used and in if statements, here is what I changed the line to (I think it works like the other one, but not sure how the other one does exactly what the following line which I changed does):

phi = n if n > 1 else False

Please could someone clear-up how the line that I don't understand works?

Coding Grind
  • 111
  • 6

4 Answers4

3

As can be seen in the Python docs, Python logical operators are not necessarily "purely Boolean". In particular, and and or are not actually guaranteed to return True or False. Instead, they return one of their operands. Here's how Python defines the value of x and y:

if x is false, then x, else y

"False" in this context does not mean that x has to be the value False. Instead, it just has to be anything with a falsy value, like a zero of any type or an empty sequence or collection.

In this case, when n > 1 evaluates False, the operator short-circuits and returns n > 1, AKA False. But if n > 1 evaluates True, the operator simply returns n without modifying it in any way, as the docs describe.

Mark Snyder
  • 1,635
  • 3
  • 12
2

The truth table for a and b looks like this:

True  and True  == True
True  and False == False
False and True  == False
False and False == False

We can observe three things:

  • When a is True, the result is always the same as b.
  • When a is False, the result is always False, in other words, it is always the same as a.
  • When a is False, b is completely irrelevant, so we don't even need to evaluate it.

Note that in Python, True and False are not the only objects that have a boolean value. In fact, every single object in Python has a boolean value. E.g. 0 has a falsey value, "Hello" has a truthy value, and so on.

So, with the optimizations we discovered about the truth table, and the added condition that we need to handle values other than True and False, we can construct the following, revised, truth table:

a and b == a # if `a` is *falsey*
a and b == b # if `a` is *truthy*

This matches up with the documentation of and:

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

Similar reasoning applies to or:

a or b == b # if `a` is *falsey*
a or b == a # if `a` is *truthy*

So, the result of the line in question:

phi = n > 1 and n

will be that phi is assigned False if n <= 1 and n if n > 1.

The further computation that is performed with phi in turn works because False is equivalent to 0 in a numeric context, i.e.

False + 1 ==  1
False - 1 == -1

This makes the rest of the algorithm work, which contains statements like:

phi -= phi // p

Where arithmetic is performed with the value of phi.

See the documentation on the numeric types for details, which contains the following statement [bold emphasis mine]:

There are three distinct numeric types: integers, floating point numbers, and complex numbers. In addition, Booleans are a subtype of integers.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
1

First, it's first checking if the first evaluation is True or False (Null value are considered false). Then if it's True, will return the second value. In this case, n.

More details:

> if n = 3
> 1. phi = n > 1 and n
> 2. phi = 3 > 1 and 3
> 3. phi = True and 3
> 4. phi = 3
  • How does `True and True` become 3? – DYZ May 22 '20 at 08:39
  • Close! But there's no Boolean conversion of the second operand at all, because there doesn't need to be. If the first operand is truthy, `and` just returns the second operand. This produces the correct result whether the second operand is truthy or falsy. – Mark Snyder May 22 '20 at 08:47
  • It's first checking if the evaluation if True and if so, the latest value checked is assigned. In this case, it's n. – Sébastien De Spiegeleer May 22 '20 at 08:48
1

From section 6.11 of the documentation:

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful, e.g., if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value. Because not has to create a new value, it returns a boolean value regardless of the type of its argument (for example, not 'foo' produces False rather than ''.)

So it first check if n > 1, if it is true, then it return s n, otherwise it returns False.

Community
  • 1
  • 1
Siong Thye Goh
  • 3,518
  • 10
  • 23
  • 31