Advanced Parameters and Scope

Now that you've learned the basics of functions, let's explore some advanced techniques. How many ways can you write parameters? What does "variable scope" mean? What is recursion? These concepts will take your understanding of functions to the next level.


1. Default Parameters

Default parameters let you omit arguments when calling a function:

Example: Basic Default Parameters

PYTHON
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")              # Hello, Alice!
greet("Bob", "Hi")          # Hi, Bob!
greet("Charlie", "Hey")     # Hey, Charlie!
▶ Try it Yourself

⚠️ The Default Parameter Pitfall

Default parameter values are evaluated only once, at function definition time, not each time the function is called. If the default is a mutable object (like a list or dictionary), this can lead to unexpected behavior:

Example: Mutable Default Pitfall

PYTHON
def add_item(item, items=[]):   # ❌ Dangerous!
    items.append(item)
    return items

print(add_item("apple"))     # ['apple']
print(add_item("banana"))    # ['apple', 'banana'] — not ['banana']!
print(add_item("orange"))    # ['apple', 'banana', 'orange']
▶ Try it Yourself

Why: The empty list items=[] is created once at function definition. Every subsequent call appends to the same list.

Correct approach: Use None as the default and create a new list inside the function:

Example: Safe Default Parameter

PYTHON
def add_item(item, items=None):  # ✅ Safe
    if items is None:
        items = []
    items.append(item)
    return items

print(add_item("apple"))     # ['apple']
print(add_item("banana"))    # ['banana']
print(add_item("orange"))    # ['orange']
▶ Try it Yourself
💡 Golden rule: Default parameters should always be immutable values (None, numbers, strings, tuples). Never use mutable objects like lists or dictionaries as defaults.


2. Keyword Arguments

When calling a function, you can specify values by parameter name, allowing you to pass arguments out of order:

Example: Keyword Arguments

PYTHON
def create_user(name, age, city):
    print(f"User: {name}, {age} years old, from {city}")

# Positional arguments — must be in order
create_user("Alice", 25, "Beijing")

# Keyword arguments — specify parameter names, order doesn't matter
create_user(age=30, city="Shanghai", name="Bob")
create_user(name="Charlie", city="Guangzhou", age=22)

# Mixed — positional first, keyword second
create_user("Diana", city="Shenzhen", age=28)
# create_user(name="Eve", 35, "Chengdu")   ❌ Keyword args can't precede positional
▶ Try it Yourself

3. *args: Variable Positional Arguments

If you don't know how many arguments a function will receive, use *args:

Example: *args for Sum Function

PYTHON
def sum_all(*numbers):
    """Accepts any number of numbers and returns their sum"""
    total = 0
    for n in numbers:
        total += n
    return total

print(sum_all(1, 2))                # 3
print(sum_all(1, 2, 3, 4, 5))      # 15
print(sum_all())                    # 0 — no arguments also works
▶ Try it Yourself

*args packs all positional arguments into a tuple:

Example: Inspecting args

PYTHON
def show_args(*args):
    print(f"Received {len(args)} arguments: {args}")
    for i, arg in enumerate(args, 1):
        print(f"  #{i}: {arg}")

show_args("apple", "banana", "orange")
▶ Try it Yourself

4. **kwargs: Variable Keyword Arguments

**kwargs accepts any number of keyword arguments and packs them into a dictionary:

Example: **kwargs for Building User Profiles

PYTHON
def create_profile(**info):
    """Create a user profile, accepting any amount of info"""
    print("User Profile:")
    for key, value in info.items():
        print(f"  {key}: {value}")

create_profile(name="Alice", age=25, city="Beijing", job="Engineer")
▶ Try it Yourself

Output:

TEXT
User Profile:
  name: Alice
  age: 25
  city: Beijing
  job: Engineer

Example: Combining *args and **kwargs

PYTHON
def advanced_function(a, b, *args, **kwargs):
    print(f"Positional: a={a}, b={b}")
    print(f"Extra positional: {args}")
    print(f"Keyword: {kwargs}")

advanced_function(1, 2, 3, 4, 5, name="Alice", age=25)
# Positional: a=1, b=2
# Extra positional: (3, 4, 5)
# Keyword: {'name': 'Alice', 'age': 25}
▶ Try it Yourself
💡 Parameter order must be fixed: normal parameters → *args → default parameters → **kwargs


5. Scope: LEGB Rule

Where can a variable be accessed? This is determined by scope. Python has four levels of scope:

Example: LEGB Scope Nesting

PYTHON
# Global scope
x = 10          # Global variable

def outer():
    # Enclosing function scope
    x = 20      # This is outer's local x, different from the global x
    
    def inner():
        # Local scope
        x = 30  # This is inner's local x
        print(f"inner: {x}")     # 30
    
    inner()
    print(f"outer: {x}")         # 20

outer()
print(f"global: {x}")            # 10
▶ Try it Yourself

LEGB stands for:

Python looks up variables in L → E → G → B order.

global and nonlocal

To modify a global variable inside a function, use global:

Example: Using global

PYTHON
count = 0

def increment():
    global count     # Declare intent to modify the global variable
    count += 1

increment()
increment()
print(count)         # 2
▶ Try it Yourself
⚠️ Minimize use of global. Global variables make code harder to understand and debug. Functions should receive input through parameters and return output through return, not secretly modify global variables.


6. Recursion Basics

Recursion is when a function calls itself. The core idea: break a big problem into smaller, similar sub-problems.

Example: Recursive Factorial

PYTHON
def factorial(n):
    """Calculate n! (n factorial)"""
    if n <= 1:
        return 1          # Termination condition
    return n * factorial(n - 1)   # Recursive call

print(factorial(5))        # 120 (5×4×3×2×1)
▶ Try it Yourself

Execution:

TEXT
factorial(5) = 5 * factorial(4)
            = 5 * 4 * factorial(3)
            = 5 * 4 * 3 * factorial(2)
            = 5 * 4 * 3 * 2 * factorial(1)
            = 5 * 4 * 3 * 2 * 1
            = 120

Example: Fibonacci Sequence (Difficulty ⭐⭐⭐)

PYTHON
def fibonacci(n):
    """Return the nth Fibonacci number (starting from 0)"""
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

# Print first 10
for i in range(10):
    print(fibonacci(i), end=" ")
# Output: 0 1 1 2 3 5 8 13 21 34
▶ Try it Yourself
💡 Two essential elements of recursion:Termination condition (otherwise infinite recursion → stack overflow). ② Recursive condition (each call moves closer to the termination). Not all problems suit recursion — if a loop works, prefer the loop. Recursion is ideal for tree structures, divide-and-conquer algorithms, etc.


Common Use Cases


❓ FAQ

Q Can I rename *args and kwargs?
A Yes. *args and kwargs are just naming conventions — the asterisks are what matter. You could write *numbers, **options. But following convention is recommended so other Python programmers immediately understand. ⚠️ Q: Recursion vs loops — which is better? A: If a loop can solve the problem, prefer the loop. Loops have better performance, won't cause stack overflow, and are easier to understand. Recursion suits two scenarios: tree structure traversal (directories, JSON) and mathematically recursive definitions (factorial, Fibonacci). Recursion is more concise but harder to understand. Q: Why can I read a global variable inside a function but not modify it? A: When reading, Python finds the global variable by following LEGB rules. But when assigning, Python creates a new local variable by default — x = 10 inside a function is treated as "create a local variable x." If you truly need to modify a global, use global. But that usually means your design could be improved.

📖 Summary

  • Default parameters add flexibility; never use mutable objects as defaults
  • Keyword arguments let you pass by name, not position
  • *args packs extra positional args into a tuple; **kwargs packs keyword args into a dict
  • Parameter order: normal → *args → defaults → **kwargs
  • LEGB rule determines variable lookup order: Local → Enclosing → Global → Built-in
  • global modifies global variables from inside a function; minimize its use
  • Recursion is a function calling itself; needs a termination condition and a recursive condition

📝 Exercises

  1. Basic (Difficulty ⭐): Write a function multiply(*nums) that accepts any number of numbers and returns their product. If no arguments, return 0.

  2. Intermediate (Difficulty ⭐⭐): Write a function create_student(name, **scores) that receives a student name and any number of subject scores (keyword arguments), calculates and returns the average. Example call: create_student("Alice", Chinese=85, Math=92, English=78).

  3. Challenge (Difficulty ⭐⭐⭐): Write a recursive function sum_digits(n) that calculates the sum of digits of a positive integer. For example, sum_digits(123) returns 1+2+3=6. Hint: Modulo 10 gives the last digit; floor division by 10 removes it. Termination condition: n < 10.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏