Execute Program

Python for Programmers: Default Argument Values

Welcome to the Default Argument Values lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • When we call a function, we have to pass the correct number of arguments. If we forget an argument, that's an error.

  • >
    def greet(name, excited):
    punctuation = ("!" if excited else ".")
    return f"Hello {name}{punctuation}"

    greet("Amir")
    Result:
    TypeError: greet() missing 1 required positional argument: 'excited'Pass Icon
  • Sometimes we want to make an argument optional. The next example makes excited optional, defaulting to False. Note the difference in the def line.

  • >
    def greet(name, excited=False):
    punctuation = ("!" if excited else ".")
    return f"Hello {name}{punctuation}"
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    greet("Amir")
    Result:
    'Hello Amir.'Pass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    greet("Betty", True)
    Result:
    'Hello Betty!'Pass Icon
  • The default argument syntax may remind you of the kwarg syntax. They both concern function arguments and they both use =.

  • Despite their similar syntax, these language features are separate. We specify default argument values with arg_name=default_value when defining a function, as shown above. We provide kwargs with arg_name=some_value when calling a function.

  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    greet("Cindy", excited=True)
    Result:
    'Hello Cindy!'Pass Icon
  • Although default arguments and kwargs are two different language features, they do tend to show up together. It's considered good style to use kwargs when overriding a default argument value. This makes it clear that we're doing something unusual.

  • For example, when we see a call like greet("Cindy", True), it doesn't show us that we're overriding a default argument. But when we see greet("Cindy", excited=True), the kwarg suggests that something unusual is happening.

  • This is even more important when functions have multiple default arguments. For example, we can expand our greet function to take three arguments, two of which are optional.

  • >
    greetings = {
    "en": "Hello",
    "fr": "Bonjour"
    }

    def greet(name, excited=False, language="en"):
    greeting = greetings[language]
    punctuation = ("!" if excited else ".")
    return f"{greeting} {name}{punctuation}"
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    greet("Amir")
    Result:
    'Hello Amir.'Pass Icon
  • We have a lot of flexibility when calling functions like this. In the next example, we pass a value for the first argument (name), we omit the second argument (excited), and we pass a value for the third argument (language). This is perfectly legal, even though we left out the middle argument!

  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    greet("Amir", language="fr")
    Result:
    'Bonjour Amir.'Pass Icon
  • Here's a code problem:

    This get_cat(owner_name) function returns the cat owned by that owner. Modify the function to work when we don't pass an owner_name at all, by giving owner_name a default value of "Unknown".

    cats = {
    "Amir": "Ms. Fluff",
    "Betty": "Keanu",
    "Wilford": "Wilford",
    "Unknown": "No cat"
    }
    def get_cat(owner_name="Unknown"):
    return cats[owner_name]
    assert get_cat("Betty") == "Keanu"
    assert get_cat() == "No cat"
    Goal:
    No errors.
    Yours:
    No errors.Pass Icon
  • Default arguments can seem simple at first, but there's one important catch, which has led to many subtle bugs in real-world systems. The question is: when does Python evaluate the default value? Try to guess what value we get in the next example.

  • >
    default_value = 3

    # When is the default value evaluated? Once, when the function is defined? Or
    # each time the function is called?
    def f(x=default_value):
    return x

    default_value = 4
    f()
    Result:
    3Pass Icon
  • There are two possible ways for that code to work, both of which make some sense:

    1. The default value expression is evaluated only once, when the function is defined. If default_value changes later, x's default value is still 3. This is how Python works.
    2. The default value expression is evaluated every time the function is called. If default_value changes, and we then call the function, x gets the new value of 4. This is how JavaScript and Ruby work.
  • If you're used to (2) above, it's important to remember that Python actually works like (1)! This will help you avoid subtle, frustrating bugs.

  • To reiterate, here are side-by-side versions of the function in Python and JavaScript, showing their different behavior.

  • >
    # This is Python.
    default_value = 3

    def f(x=default_value):
    return x

    default_value = 4
    f()
    Result:
  • >
    /* This is JavaScript, not Python! */
    let default_value = 3;

    function f(x=default_value) {
    return x;
    }

    default_value = 4;
    f();
    Result: