Functions in Depth
Default values, keyword arguments, *args and **kwargs, and how scope decides where a variable lives.
What you will learn
- Give parameters default values
- Accept any number of arguments with *args and **kwargs
- Understand local vs global scope
Default values
A default value lets a parameter be optional — if the caller does not pass one, the function uses a fallback you chose. You set it with = right in the function definition.
def greet(name, greeting="Hello"):
return greeting + ", " + name + "!"
print(greet("Asha")) # uses the default
print(greet("Ravi", "Welcome")) # overrides itThe parameter greeting="Hello" has a default. In the first call we pass only name, so greeting falls back to "Hello", giving Hello, Asha!. In the second call we pass a second value, "Welcome", which replaces the default, giving Welcome, Ravi!. Defaults make a function flexible without forcing the caller to supply every value.
Note: Output: Hello, Asha! Welcome, Ravi!
Keyword arguments
Normally Python matches arguments by position (first value to first parameter). But you can also pass them by name, called keyword arguments — then the order does not matter and the call reads more clearly.
def book(room, nights, breakfast):
return f"{room} for {nights} nights, breakfast={breakfast}"
print(book(nights=2, room="Deluxe", breakfast=True))Even though we wrote nights first and room second, naming each argument tells Python exactly where it goes — so room still gets "Deluxe" and nights gets 2. Keyword arguments are great when a function has many parameters and you want the call to be self-explaining.
Note: Output: Deluxe for 2 nights, breakfast=True
*args: accept any number of values
Sometimes you do not know how many values the caller will pass — think of a function that adds up any amount of numbers. Putting a * before a parameter name (the convention is *args) collects all the extra positional values into a tuple for you.
def total(*numbers):
result = 0
for n in numbers:
result = result + n
return result
print(total(2, 3)) # 5
print(total(1, 2, 3, 4)) # 10The *numbers parameter scoops up all the values passed in — in the first call that is (2, 3), in the second (1, 2, 3, 4). Inside the function numbers is just a tuple, so we loop over it and add everything up. The same function happily handles two numbers or four, because *args does not fix the count.
Note: Output: 5 10
**kwargs: accept named extras
The double-star version, **kwargs, collects any extra keyword arguments into a dictionary — each name becomes a key and each value a value. Handy when a function should accept flexible, named options.
def profile(**details):
for key, value in details.items():
print(key, "->", value)
profile(name="Asha", age=22, city="Lucknow")Each named argument in the call becomes a key–value pair inside the details dictionary: name→Asha, age→22, city→Lucknow. We then loop over .items() (just like a normal dict) and print each pair. The function never had to know in advance which details would be passed.
Note: Output: name -> Asha age -> 22 city -> Lucknow
Scope: where a variable lives
Scope is the rule for where a variable can be seen. A variable created inside a function is local — it exists only there and vanishes when the function ends. A variable created outside all functions is global — visible everywhere. This keeps each function tidy and self-contained.
message = "global" # global variable
def show():
message = "local" # a separate local variable
print("inside:", message)
show()
print("outside:", message)There are two different message variables here. The one inside show() is local — it only exists during the call, so inside: local prints. The outer message is global and untouched, so after the function finishes, outside: global prints. Changing a name inside a function does not change the global one with the same name — they live in separate scopes.
Note: Output: inside: local outside: global
Tip: Functions can read global values, but to reassign a global from inside you must say global name first. Most of the time, though, it is cleaner to pass values in as parameters and return results out — avoid reaching for global.
Q. What does *args collect the extra positional arguments into?
✍️ Practice
- Write a function with a default parameter and call it both with and without that argument.
- Write a function that uses *args to multiply any number of values together.
🏠 Homework
- Write a function average(*numbers) that returns the average of however many numbers are passed in.