Gerald baker
Gerald baker

Reputation: 31

Python logic in assignment

Given that secure is a boolean, what do the following statements do?

Especially the first statement.

  1. protocol = secure and "https" or "http"
  2. newurl = "%s://%s%s" % (protocol,get_host(request),request.get_full_path())

Upvotes: 3

Views: 4108

Answers (5)

yfeldblum
yfeldblum

Reputation: 65435

In psuedocode:

protocol = (if secure then "https" else "http")
newurl = protocol + "://" + get_host(request) + request.get_full_path()

Upvotes: 0

Doug
Doug

Reputation: 9100

Python generalises boolean operations a bit, compared to other languages. Before the "if" conditional operator was added (similar to C's ?: ternary operator), people sometimes wrote equivalent expressions using this idiom.

and is defined to return the first value if it's boolean-false, else returns the second value:

a and b == a if not bool(a) else b #except that a is evaluated only once

or returns its first value if it's boolean-true, else returns its second value:

a or b == a if bool(a) else b #except that a is evaluated only once

If you plug in True and False for a and b in the above expressions, you'll see that they work out as you would expect, but they work for other types, like integers, strings, etc. as well. Integers are treated as false if they're zero, containers (including strings) are false if they're empty, and so on.

So protocol = secure and "https" or "http" does this:

protocol = (secure if not secure else "https") or "http"

...which is

protocol = ((secure if not bool(secure) else "https") 
            if bool(secure if not bool(secure) else "https") else "http")

The expression secure if not bool(secure) else "https" gives "https" if secure is True, else returns the (false) secure value. So secure if not bool(secure) else "https" has the same truth-or-falseness as secure by itself, but replaces boolean-true secure values with "https". The outer or part of the expression does the opposite - it replaces boolean-false secure values with "http", and doesn't touch "https", because it's true.

This means that the overall expression does this:

  • if secure is false, then the expression evaluates to "http"
  • if secure is true, then the expression evaluates to "https"

...which is the result that other answers have indicated.

The second statement is just string formatting - it substitutes each of the tuple of strings into the main "format" string wherever %s appears.

Upvotes: 5

Hollister
Hollister

Reputation: 3918

The first line was answered well by the Ned and unwind.

The 2nd statement is a string replacement. Each %s is a placeholder for a string value. So if the values are:

protocol = "http"
get_host(request) = "localhost"
request.get_full_path() = "/home"

the resulting string would be:

http://localhost/home

Upvotes: 1

Ned Batchelder
Ned Batchelder

Reputation: 375584

I hate this Python idiom, it's completely opaque until someone explains it. In 2.6 or higher, you'd use:

protocol = "https" if secure else "http"

Upvotes: 13

unwind
unwind

Reputation: 399833

It sets protocol to "https" if secure is true, else it sets it to "http".

Try it in the interpreter:

>>> True and "https" or "http"
'https'
>>> False and "https" or "http"
'http'

Upvotes: 5

Related Questions