Skip to content
Laviyx Learn

Try

Python Functions Deep Dive Practice

Practise default and keyword arguments, *args and **kwargs, returning several values, scope, lambda functions and recursion.

Intermediate10 problemsUpdated

Review first: Parameters, Arguments, Return Values, Scope, Lambda Functions, Recursion

  1. 1.Default and keyword arguments

    Intermediate

    Write greet(name, greeting="Hello", punctuation="!") that returns a greeting string. Call it as greet("Asha"), greet("Ravi", "Welcome") and greet("Meera", punctuation="?").

    Show hint

    Parameters with defaults go after the ones without. A keyword argument lets you skip over greeting.

    Show solution
    Python
    def greet(name, greeting="Hello", punctuation="!"):
        return f"{greeting}, {name}{punctuation}"
    
    
    print(greet("Asha"))
    print(greet("Ravi", "Welcome"))
    print(greet("Meera", punctuation="?"))
    Output
    Hello, Asha!
    Welcome, Ravi!
    Hello, Meera?
  2. 2.Average of any number of values

    Intermediate

    Write average(*numbers) that returns the average of any number of arguments, or None if it is called with none. Print average(4, 8, 6), average(10) and average().

    Show hint

    *numbers collects the arguments into a tuple. An empty tuple is falsy.

    Show solution
    Python
    def average(*numbers):
        if not numbers:
            return None
        return sum(numbers) / len(numbers)
    
    
    print(average(4, 8, 6))
    print(average(10))
    print(average())
    Output
    6.0
    10.0
    None
  3. 3.Build a profile with **kwargs

    Intermediate

    Write profile(name, **details) that prints the name, then each extra detail as - key: value. Call it with profile("Asha", city="Pune", role="Analyst", years=3).

    Show hint

    **details collects keyword arguments into a dictionary.

    Show solution
    Python
    def profile(name, **details):
        print(name)
        for key, value in details.items():
            print(f"- {key}: {value}")
    
    
    profile("Asha", city="Pune", role="Analyst", years=3)
    Output
    Asha
    - city: Pune
    - role: Analyst
    - years: 3
  4. 4.Return several values

    Intermediate

    Write stats(values) that returns the smallest value, the largest value and the average (rounded to 2 decimals) in one return. Unpack the result of stats([12, 7, 21, 9]) into three variables and print them.

    Show hint

    return a, b, c returns a tuple, which you can unpack with low, high, avg = stats(...).

    Show solution
    Python
    def stats(values):
        return min(values), max(values), round(sum(values) / len(values), 2)
    
    
    low, high, avg = stats([12, 7, 21, 9])
    
    print(low, high, avg)
    print(stats([12, 7, 21, 9]))
    Output
    7 21 12.25
    (7, 21, 12.25)
  5. 5.Predict the scope

    Intermediate

    What does this print? Work it out first, then run it.

    Python
    count = 10
    
    def change():
        count = 99
        print("inside:", count)
    
    def change_global():
        global count
        count = 50
    
    change()
    print("after change:", count)
    change_global()
    print("after change_global:", count)
    Show hint

    Assigning to a name inside a function creates a new local variable, unless the name is declared global.

    Show solution
    Python
    count = 10
    
    def change():
        count = 99
        print("inside:", count)
    
    def change_global():
        global count
        count = 50
    
    change()
    print("after change:", count)
    change_global()
    print("after change_global:", count)
    Output
    inside: 99
    after change: 10
    after change_global: 50

    change() creates its own local count, so the global one stays 10. change_global() declares global count, so it changes the module-level variable. In real code, prefer returning a value over changing globals.

  6. 6.Sort with a lambda

    Intermediate

    Sort students = [("Asha", 88), ("Ravi", 95), ("Meera", 88), ("John", 72)] by score from highest to lowest, with ties sorted alphabetically by name, and print the result.

    Show hint

    key=lambda s: (-s[1], s[0]) sorts by the negative score first, then by the name.

    Show solution
    Python
    students = [("Asha", 88), ("Ravi", 95), ("Meera", 88), ("John", 72)]
    
    ranked = sorted(students, key=lambda s: (-s[1], s[0]))
    
    for name, score in ranked:
        print(name, score)
    Output
    Ravi 95
    Asha 88
    Meera 88
    John 72
  7. 7.filter and map

    Intermediate

    From prices = [120, 45, 300, 80, 15], keep the prices over 50 and add 18% tax to each, rounded to 2 decimals. Use filter and map with lambdas, then the same with a list comprehension.

    Show hint

    filter(lambda p: p > 50, prices) keeps items; map(lambda p: ..., items) transforms them. Wrap the result in list() to see it.

    Show solution
    Python
    prices = [120, 45, 300, 80, 15]
    
    with_tax = list(map(lambda p: round(p * 1.18, 2), filter(lambda p: p > 50, prices)))
    print(with_tax)
    
    same = [round(p * 1.18, 2) for p in prices if p > 50]
    print(same)
    Output
    [141.6, 354.0, 94.4]
    [141.6, 354.0, 94.4]

    Both give the same result. Most Python programmers find the list comprehension easier to read.

  8. 8.Sum of digits, recursively

    Intermediate

    Write a recursive function digit_sum(n) that adds up the digits of a non-negative integer, so digit_sum(4096) is 4 + 0 + 9 + 6 = 19. Print digit_sum(4096) and digit_sum(7).

    Show hint

    The base case is a single digit (n < 10). Otherwise, the last digit is n % 10 and the rest of the number is n // 10.

    Show solution
    Python
    def digit_sum(n):
        if n < 10:
            return n
        return n % 10 + digit_sum(n // 10)
    
    
    print(digit_sum(4096))
    print(digit_sum(7))
    Output
    19
    7
  9. 9.Flatten a nested list

    Intermediate

    Write a recursive function flatten(items) that turns [1, [2, 3], [4, [5, [6]]], 7] into [1, 2, 3, 4, 5, 6, 7].

    Show hint

    For each item, if it is a list, extend the result with flatten(item); otherwise append it.

    Show solution
    Python
    def flatten(items):
        result = []
        for item in items:
            if isinstance(item, list):
                result.extend(flatten(item))
            else:
                result.append(item)
        return result
    
    
    print(flatten([1, [2, 3], [4, [5, [6]]], 7]))
    Output
    [1, 2, 3, 4, 5, 6, 7]

    Recursion is a natural fit here because the data itself is nested to an unknown depth.

  10. 10.The mutable default trap

    Intermediate

    This function is meant to start a new list on every call, but it has a bug. Predict the output, then fix it.

    Python
    def add_item(item, basket=[]):
        basket.append(item)
        return basket
    
    print(add_item("apple"))
    print(add_item("bread"))
    Show hint

    A default value is created once, when the function is defined, not on every call.

    Show solution
    Python
    def add_item_buggy(item, basket=[]):
        basket.append(item)
        return basket
    
    print(add_item_buggy("apple"))
    print(add_item_buggy("bread"))  # the same list is reused!
    
    
    def add_item(item, basket=None):
        if basket is None:
            basket = []
        basket.append(item)
        return basket
    
    print(add_item("apple"))
    print(add_item("bread"))
    Output
    ['apple']
    ['apple', 'bread']
    ['apple']
    ['bread']

    Never use a mutable value (a list, dictionary or set) as a default argument. Use None and create the new object inside the function.