Blog


Two Python ‘features’ I learned today

Every programming language has its own funny, unusual, and good-to-know language constructs. Today, I came to learn two such language constructs in Python.

Finding a needle in a haystack

Consider the following way to check if a needle exists in a haystack:

print("Needle" in "Haystack")

When run, this will print False, as one would expect, since “Haystack” doesn’t contain a substring “Needle”. Python can also check if the “Needle” in a list or tuple, like this:

print("Needle" in ["Needless"])
print("Needle" in ("Needless"))

The first would print False, since “Needle” as a whole word is not an element in the list. The second however would print True, because the 1-tuple is not defined correctly. Consequently, the parenthesis are ignored and “Needle” is found a substring of “Needless”. When the 1-tuple is defined the right way (note the trailing comma) False will be printed:

print("Needle" in ("Needless",))

Something to be aware of!

Using a default value for a function argument

It is very convenient to be able to specify some default value for function arguments. For example like this:

def print_message(message, log_level="INFO"):
    if log_level is "INFO":
        print("INFO:   ", message)
    elif log_level is "WARNING":
        print("WARNING:", message)
    elif log_level is "ERROR":
        print("ERROR   ", message)

If we would call the function with print_message(“Smells like teen spirit”), the “INFO: Smells like teen spirit” would be printed. Note here that the default value for log_level is immutable; it is a string constant, not an object. Now consider the following:

def add_to_basket(item, basket=[]):
    basket.append(item)
    return basket

if __name__ in "__main__":
    print add_to_basket("Bananas")
    print add_to_basket("Apple")
    print add_to_basket("Pear")

Since basket a function argument, I would expect it to have a scope local to the function. In reality however, the three print statements would subsequently output:

['Bananas']
['Bananas', 'Apple']
# and
['Bananas', 'Apple', 'Pear']

In other words, basket behaves like a static variable in C would. It appears that Python treats functions just like classes, and that default function arguments are a kind of member data. As long as the default value is immutable you won’t experience this behavior, but when it is a mutable value (a list, dictionary, or other object) the function argument will behave this way.

Good to keep in mind that if I need to use an mutable object as default argument value, I should use the value None and check for this value inside the function in order to set it to its actual default value, e.g.:

def add_to_basket(item, basket=None):
    if basket is None:
        basket=[]
    basket.append(item)
    return basket

In case basket equals None, the above example would return a list with only the given item in it.




No more Dutch

So far this website has been a mixture of blog-posts in Dutch and pages in both Dutch and English. The website gets a bit messy this way. Besides that it feels stupid to put time and effort in writing content in more than one language considering that most visitors can read English, and considering that I have little free time anyway. As such, I decided to write posts and pages in English only from now on.