Further information#

What is the difference between a Python list and a Python tuple?#

Two of the most used Python iterables are lists and tuples. In practice they have a number of similarities, they are both ordered collections of objects that can be used in list comprehensions as well as in other ways.

  • Tuples are immutable

  • Lists are mutable

This means that once created tuples cannot be changed and lists can.

As a general rule of thumb: if you do not need to modify your iterable then use a tuple as they are more computationally efficient.

Why does the sum of booleans count the Trues?#

In the tutorial and elsewhere you created a list of booleans and then took the sum. Here are some of the steps:

samples = ("Red", "Red", "Blue")
booleans = [sample == "Red" for sample in samples]
booleans
[True, True, False]

When you take the sum of that list you get a numeric value:

sum(booleans)
2

This has in fact counted the True values as 1 and the False values as 0.

int(True)
1
int(False)
0

What is the difference between print and return?#

In functions you use the return statement. This does two things:

  1. Assigns a value to the function run;

  2. Ends the function.

The print statement only displays the output.

As an example create the following set:

\[ S = \{f(x)\text{ for }x \in \{0, \pi / 4, \pi / 2, 3\pi / 4\}\} \]

where \(f(x)= \cos^2(x)\).

The correct way to do this is:

import sympy as sym


def f(x):
    """
    Return the square of the cosine of x
    """
    return sym.cos(x) ** 2


S = [f(x) for x in (0, sym.pi / 4, sym.pi / 2, 3 * sym.pi / 4)]
S
[1, 1/2, 0, 1/2]

If you replaced the return statement in the function definition with a print you obtain:

def f(x):
    """
    Return the square of the cosine of x
    """
    print(sym.cos(x) ** 2)


S = [f(x) for x in (0, sym.pi / 4, sym.pi / 2, 3 * sym.pi / 4)]
1
1/2
0
1/2

The function has been run and it displays the output.

However if you look at what S is you see that the function has not returned anything:

S
[None, None, None, None]

How does Python sample randomness?#

When using the Python random module you are in fact generating a pseudo random process. True randomness is actually not common.

Pseudo randomness is an important area of mathematics as strong algorithms that create unpredictable sequences of numbers are vital to cryptographic security.

The specific algorithm using in Python for randomness is called the Mersenne twister algorithm is state of the art.

You can read more about this here: https://docs.python.org/3/library/random.html#module-random.

What is the difference between a docstring and a comment#

In Python it is possible to write statements that are ignored using the # symbol. This creates something called a “comment”. For example:

# create a list to represent the tokens in a bag
bag = ["Red", "Red", "Blue"]

A docstring however is something that is “attached”’ to a function and can be accessed by Python. If you rewrite the function to sample the experiment of the tutorial without a docstring but using comments you will have:

def sample_experiment(bag):
    # Select a token
    selected_token = pick_a_token(container=bag)

    # If the token is red then the probability of selecting heads is 2/3
    if selected_token == "Red":
        probability_of_selecting_heads = 2 / 3
    # Otherwise it is 1 / 2
    else:
        probability_of_selecting_heads = 1 / 2

    # Select a coin according to the probability.
    if random.random() < probability_of_selecting_heads:
        coin = "Heads"
    else:
        coin = "Tails"

    # Return both the selected token and the coin.
    return selected_token, coin

Now if you try to access the help for the function you will not get it:

help(sample_experiment)
Help on function sample_experiment in module __main__:

sample_experiment(bag)

Furthermore, if you look at the code with comments you will see that because of the choice of variable names the comments are in fact redundant.

In software engineering it is generally accepted that comments indicate that your code is not clear and so it is preferable to write clear documentation explaining why something is done through docstrings.

def sample_experiment(bag):
    """
    This samples a token from a given bag and then
    selects a coin with a given probability.

    If the sampled token is red then the probability
    of selecting heads is 2/3 otherwise it is 1/2.

    This function returns both the selected token
    and the coin face.
    """
    selected_token = pick_a_token(container=bag)

    if selected_token == "Red":
        probability_of_selecting_heads = 2 / 3
    else:
        probability_of_selecting_heads = 1 / 2

    if random.random() < probability_of_selecting_heads:
        coin = "Heads"
    else:
        coin = "Tails"
    return selected_token, coin

Here are some resources on this: