You're writing a logging function that should accept any number of messages. Or a config function that takes arbitrary key-value options. *args and **kwargs let you accept variable arguments without knowing them in advance.

Accept any positional arguments

Use *args to collect extra positional arguments.

args.py
Replay: real traced execution (multi-file project)
def main():
    print("=== *args: Variable Positional Arguments ===\n")

    # Any number of arguments
    print("sum_all with different counts:")
    print(f"sum_all(1, 2) = {sum_all(1, 2)}")
    print(f"sum_all(1, 2, 3) = {sum_all(1, 2, 3)}")
    print(f"sum_all(1, 2, 3, 4, 5) = {sum_all(1, 2, 3, 4, 5)}")
    print(f"sum_all() = {sum_all()}")  # Zero args OK!

    print("\n=== What is *args? ===")
    show_args(10, 20, 30)

    print("\n=== Required + *args ===")
    greet("Hello", "Alice", "Bob", "Charlie")
    greet("Hi", "Dave")

    print("\n=== Type Hints with *args ===")
    result = concat_strings("Hello", " ", "World", "!")
    print(f"concat_strings result: {result}")

def sum_all(*numbers):
    """Sum any number of values."""
    total = 0
    for n in numbers:
        total += n
    return total

def show_args(*args):
    """Show what args contains."""
    print(f"args = {args}")
    print(f"type(args) = {type(args).__name__}")
    print(f"len(args) = {len(args)}")

def greet(greeting, *names):
    """Greet multiple people."""
    for name in names:
        print(f"{greeting}, {name}!")

def concat_strings(*strings: str) -> str:
    """Concatenate any number of strings (typed)."""
    return "".join(strings)

if __name__ == "__main__":
    main()
  1. def main():

    1#@var=default,typed2def main():3    print("=== *args: Variable Positional Arguments ===\n")4    5    # Any number of arguments  #?any6    print("sum_all with different counts:")7    print(f"sum_all(1, 2) = {sum_all(1, 2)}")8    print(f"sum_all(1, 2, 3) = {sum_all(1, 2, 3)}")
    output=== *args: Variable Positional Arguments ===
    sum_all with different counts:
  2. total ← 0

    pass 1 of 4
    25def sum_all(*numbers(1, 2)):  #?starargs26    """Sum any number of values."""27    total→ 0 = 028    for n in numbers:
    All 4 passes — pass 1 is the card above
    passnumberstotal
    1(1, 2)0
    2(1, 2, 3)0
    3(1, 2, 3, 4, 5)0
    4()0
  3. total ← 1

    pass 1 of 10
    27total = 028for n1 in numbers(1, 2):29    total→ 1 += n130return total
    All 10 passes — pass 1 is the card above
    passnnumberstotal
    11(1, 2)0 1
    22(1, 2)1 3
    31(1, 2, 3)0 1
    42(1, 2, 3)1 3
    53(1, 2, 3)3 6
    61(1, 2, 3, 4, 5)0 1
    72(1, 2, 3, 4, 5)1 3
    83(1, 2, 3, 4, 5)3 6
    94(1, 2, 3, 4, 5)6 10
    105(1, 2, 3, 4, 5)10 15
  4. return total

    29    total += n30return total3
  5. print(f"sum_all(1, 2) = {sum_all(1, 2)}")

    6print("sum_all with different counts:")7print(f"sum_all(1, 2) = {sum_all(1, 2)}")8print(f"sum_all(1, 2, 3) = {sum_all(1, 2, 3)}")9print(f"sum_all(1, 2, 3, 4, 5) = {sum_all(1, 2, 3, 4, 5)}")
    outputsum_all(1, 2) = 3
  6. return total

    29    total += n30return total6
  7. print(f"sum_all(1, 2, 3) = {sum_all(1, 2, 3)}")

    7print(f"sum_all(1, 2) = {sum_all(1, 2)}")8print(f"sum_all(1, 2, 3) = {sum_all(1, 2, 3)}")9print(f"sum_all(1, 2, 3, 4, 5) = {sum_all(1, 2, 3, 4, 5)}")10print(f"sum_all() = {sum_all()}")  # Zero args OK!
    outputsum_all(1, 2, 3) = 6
  8. return total

    29    total += n30return total15
  9. print(f"sum_all(1, 2, 3, 4, 5) = {sum_all(1, 2, 3, 4, 5)}")

    8print(f"sum_all(1, 2, 3) = {sum_all(1, 2, 3)}")9print(f"sum_all(1, 2, 3, 4, 5) = {sum_all(1, 2, 3, 4, 5)}")10print(f"sum_all() = {sum_all()}")  # Zero args OK!
    outputsum_all(1, 2, 3, 4, 5) = 15
  10. print(f"sum_all() = {sum_all()}") # Zero args OK!

    9print(f"sum_all(1, 2, 3, 4, 5) = {sum_all(1, 2, 3, 4, 5)}")10print(f"sum_all() = {sum_all()}")  # Zero args OK!1112print("\n=== What is *args? ===")  #?whatis13show_args(10, 20, 30)
    outputsum_all() = 0
    
    === What is *args? ===
  11. def show_args(*args): #?inspect

    12    print("\n=== What is *args? ===")  #?whatis13    show_args(10, 20, 30)14    15    print("\n=== Required + *args ===")  #?required16    greet("Hello", "Alice", "Bob", "Charlie")17    greet("Hi", "Dave")18    19    #@var=_,!20    print("\n=== Type Hints with *args ===")21    result = concat_strings("Hello", " ", "World", "!")22    print(f"concat_strings result: {result}")23    #@var=_,!2425def sum_all(*numbers):  #?starargs26    """Sum any number of values."""27    total = 028    for n in numbers:29        total += n30    return total3132def show_args(*args(10, 20, 30)):  #?inspect33    """Show what args contains."""34    print(f"args = {args(10, 20, 30)}")35    print(f"type(args) = {type(args(10, 20, 30)).__name__}")36    print(f"len(args) = {len(args(10, 20, 30))}")
    outputargs = (10, 20, 30)
    type(args) = tuple
    len(args) = 3
    
    === Required + *args ===
  12. def greet(greeting, *names): #?mixed

    pass 1 of 2
    38def greet(greetingHello, *names('Alice', 'Bob', 'Charlie')):  #?mixed39    """Greet multiple people."""40    for name in names:
  13. for name in names:

    pass 1 of 4
    39"""Greet multiple people."""40for nameAlice in names('Alice', 'Bob', 'Charlie'):41    print(f"{greetingHello}, {nameAlice}!")
    outputHello, Alice!
    All 4 passes — pass 1 is the card above
    passnamenamesgreetingstrings
    1Alice('Alice', 'Bob', 'Charlie')Hello
    2Bob('Alice', 'Bob', 'Charlie')Hello
    3Charlie('Alice', 'Bob', 'Charlie')Hello
    4Dave('Dave',)Hi('Hello', ' ', 'World', '!')
  14. def greet(greeting, *names): #?mixed

    pass 2 of 2
    38def greet(greetingHi, *names('Dave',)):  #?mixed39    """Greet multiple people."""40    for name in names:
  15. def concat_strings(*strings: str) -> str: #?typed

    43#@var=_,!44def concat_strings(*strings('Hello', ' ', 'World', '!'): str) -> str:  #?typed45    """Concatenate any number of strings (typed)."""46    return "".join(strings('Hello', ' ', 'World', '!'))47#@var=_,!
  16. result ← Hello World!

    20    print("\n=== Type Hints with *args ===")21    result→ Hello World! = concat_strings("Hello", " ", "World", "!")22    print(f"concat_strings result: {resultHello World!}")23    #@var=_,!2425def sum_all(*numbers):  #?starargs26    """Sum any number of values."""27    total = 028    for n in numbers:29        total += n30    return total3132def show_args(*args):  #?inspect33    """Show what args contains."""34    print(f"args = {args}")35    print(f"type(args) = {type(args).__name__}")36    print(f"len(args) = {len(args)}")3738def greet(greeting, *names):  #?mixed39    """Greet multiple people."""40    for name in names:41        print(f"{greeting}, {name}!")4243#@var=_,!44def concat_strings(*strings: str) -> str:  #?typed45    """Concatenate any number of strings (typed)."""46    return "".join(strings)47#@var=_,!4849if __name__ == "__main__":50    main()51#@help any
    outputconcat_strings result: Hello World!

*args collects extra positional arguments into a tuple.

*args Collects variable positional arguments: `def f(*args):` - args is a tuple.

Accept any keyword arguments

Use **kwargs to collect extra keyword arguments.

kwargs.py
Replay: real traced execution (multi-file project)
def main():
    print("=== **kwargs: Variable Keyword Arguments ===\n")

    # Any keyword arguments
    print("User profiles:")
    print_info(name="Alice", age=30, city="NYC")
    print()
    print_info(name="Bob", occupation="Developer")
    print()
    print_info(username="charlie", email="c@test.com", premium=True)

    print("\n=== What is **kwargs? ===")
    show_kwargs(x=10, y=20, z=30)

    print("\n=== Building Objects ===")
    config = make_config(debug=True, timeout=30, retries=3)
    print(f"Config: {config}")

    print("\n=== With Validation ===")
    try:
        validated = create_user(name="Alice", email="alice@test.com")
        print(f"Created: {validated}")
    except ValueError as e:
        print(f"Error: {e}")

def print_info(**kwargs):
    """Print all provided info."""
    for key, value in kwargs.items():
        print(f"  {key}: {value}")

def show_kwargs(**kwargs):
    """Show what kwargs contains."""
    print(f"kwargs = {kwargs}")
    print(f"type(kwargs) = {type(kwargs).__name__}")
    print(f"keys = {list(kwargs.keys())}")

def make_config(**settings):
    """Create config dict from keyword args."""
    # Add defaults
    config = {
        'debug': False,
        'timeout': 60,
        'retries': 5
    }
    # Override with provided settings
    config.update(settings)
    return config

def create_user(**fields):
    """Create user with validation."""
    required = ['name', 'email']
    for field in required:
        if field not in fields:
            raise ValueError(f"Missing required field: {field}")
    return fields

if __name__ == "__main__":
    main()
  1. def main():

    1#@var=default,validation2def main():3    print("=== **kwargs: Variable Keyword Arguments ===\n")4    5    # Any keyword arguments  #?any6    print("User profiles:")7    print_info(name="Alice", age=30, city="NYC")8    print()
    output=== **kwargs: Variable Keyword Arguments ===
    User profiles:
  2. def print_info(**kwargs): #?doublestar

    pass 1 of 3
    29def print_info(**kwargs):  #?doublestar30    """Print all provided info."""31    for key, value in kwargs.items():
    All 3 passes — pass 1 is the card above
    passkwargssettingsconfig
    1
    2
    3{'x': 10, 'y': 20, 'z': 30}{'debug': True, 'timeout': 30, 'retries': 3}{'debug': True, 'timeout': 30, 'retries': 3} {'debug': False, 'timeout': 60, 'retries': 5}
  3. for key, value in kwargs.items():

    pass 1 of 8
    30"""Print all provided info."""31for keyname, valueAlice in kwargs{'name': 'Alice', 'age': 30, 'city': 'NYC'}.items():32    print(f"  {keyname}: {valueAlice}")
    output  name: Alice
    All 8 passes — pass 1 is the card above
    passkeyvaluekwargssettingsconfig
    1nameAlice{'name': 'Alice', 'age': 30, 'city': 'NYC'}
    2age30{'name': 'Alice', 'age': 30, 'city': 'NYC'}
    3cityNYC{'name': 'Alice', 'age': 30, 'city': 'NYC'}
    4nameBob{'name': 'Bob', 'occupation': 'Developer'}
    5occupationDeveloper{'name': 'Bob', 'occupation': 'Developer'}
    6usernamecharlie{'username': 'charlie', 'email': 'c@test.com', 'premium': True}
    7emailc@test.com{'username': 'charlie', 'email': 'c@test.com', 'premium': True}
    8premiumTrue{'username': 'charlie', 'email': 'c@test.com', 'premium': True}{'debug': True, 'timeout': 30, 'retries': 3}{'debug': True, 'timeout': 30, 'retries': 3} {'debug': False, 'timeout': 60, 'retries': 5}
  4. def show_kwargs(**kwargs): #?inspect

    13    print("\n=== What is **kwargs? ===")  #?whatis14    show_kwargs(x=10, y=20, z=30)15    16    print("\n=== Building Objects ===")  #?build17    config = make_config(debug=True, timeout=30, retries=3)18    print(f"Config: {config}")19    20    #@var=_,!21    print("\n=== With Validation ===")22    try:23        validated = create_user(name="Alice", email="alice@test.com")24        print(f"Created: {validated}")25    except ValueError as e:26        print(f"Error: {e}")27    #@var=_,!2829def print_info(**kwargs):  #?doublestar30    """Print all provided info."""31    for key, value in kwargs.items():32        print(f"  {key}: {value}")3334def show_kwargs(**kwargs):  #?inspect35    """Show what kwargs contains."""36    print(f"kwargs = {kwargs{'x': 10, 'y': 20, 'z': 30}}")37    print(f"type(kwargs) = {type(kwargs{'x': 10, 'y': 20, 'z': 30}).__name__}")38    print(f"keys = {list(kwargs{'x': 10, 'y': 20, 'z': 30}.keys())}")
    outputkwargs = {'x': 10, 'y': 20, 'z': 30}
    type(kwargs) = dict
    keys = ['x', 'y', 'z']
    
    === Building Objects ===
  5. config ← {'debug': False, 'timeout': 60, 'retries': 5}

    40def make_config(**settings):  #?return41    """Create config dict from keyword args."""42    # Add defaults43    config→ {'debug': False, 'timeout': 60, 'retries': 5} = {44        'debug': False,45        'timeout': 60,46        'retries': 547    }48    # Override with provided settings49    config→ {'debug': True, 'timeout': 30, 'retries': 3}.update(settings{'debug': True, 'timeout': 30, 'retries': 3})50    return config{'debug': True, 'timeout': 30, 'retries': 3}
  6. config ← {'debug': True, 'timeout': 30, 'retries': 3}

    16print("\n=== Building Objects ===")  #?build17config→ {'debug': True, 'timeout': 30, 'retries': 3} = make_config(debug=True, timeout=30, retries=3)18print(f"Config: {config{'debug': True, 'timeout': 30, 'retries': 3}}")1920#@var=_,!21print("\n=== With Validation ===")22try:
    outputConfig: {'debug': True, 'timeout': 30, 'retries': 3}
    
    === With Validation ===
  7. required ← ['name', 'email']

    52#@var=_,!53def create_user(**fields):  #?validate54    """Create user with validation."""55    required→ ['name', 'email'] = ['name', 'email']56    for field in required:
  8. for field in required:

    pass 1 of 2
    55required = ['name', 'email']56for fieldname in required['name', 'email']:57    if field not in fields:58        raise ValueError(f"Missing required field: {field}")
  9. for field in required:

    pass 2 of 2
    55required = ['name', 'email']56for fieldemail in required['name', 'email']:57    if field not in fields:58        raise ValueError(f"Missing required field: {field}")
  10. return fields

    58            raise ValueError(f"Missing required field: {field}")59    return fields{'name': 'Alice', 'email': 'alice@test.com'}60#@var=_,!
  11. validated ← {'name': 'Alice', 'email': 'alice@test.com'}

    22    try:23        validated→ {'name': 'Alice', 'email': 'alice@test.com'} = create_user(name="Alice", email="alice@test.com")24        print(f"Created: {validated{'name': 'Alice', 'email': 'alice@test.com'}}")25    except ValueError as e:26        print(f"Error: {e}")27    #@var=_,!2829def print_info(**kwargs):  #?doublestar30    """Print all provided info."""31    for key, value in kwargs.items():32        print(f"  {key}: {value}")3334def show_kwargs(**kwargs):  #?inspect35    """Show what kwargs contains."""36    print(f"kwargs = {kwargs}")37    print(f"type(kwargs) = {type(kwargs).__name__}")38    print(f"keys = {list(kwargs.keys())}")3940def make_config(**settings):  #?return41    """Create config dict from keyword args."""42    # Add defaults43    config = {44        'debug': False,45        'timeout': 60,46        'retries': 547    }48    # Override with provided settings49    config.update(settings)50    return config5152#@var=_,!53def create_user(**fields):  #?validate54    """Create user with validation."""55    required = ['name', 'email']56    for field in required:57        if field not in fields:58            raise ValueError(f"Missing required field: {field}")59    return fields60#@var=_,!6162if __name__ == "__main__":63    main()64#@help any
    outputCreated: {'name': 'Alice', 'email': 'alice@test.com'}

**kwargs collects extra keyword arguments into a dictionary.

**kwargs Collects variable keyword arguments: `def f(**kwargs):` - kwargs is a dict.

Combine *args and **kwargs

Accept both kinds of variable arguments.

combined.py
Replay: real traced execution (multi-file project)
def main():
    print("=== Combining *args and **kwargs ===\n")

    # Both together
    log("INFO", "User logged in", user="Alice", ip="192.168.1.1")
    log("ERROR", "Connection failed", "timeout", retries=3)
    log("DEBUG", "Processing")  # Just message

    print("\n=== Full Signature Order ===")
    demonstrate_order("required", "extra1", "extra2",
                     kw_only="value", opt1="a", opt2="b")

    print("\n=== Catch-All Function ===")
    catch_all(1, 2, 3, name="test", flag=True)

def log(level, message, *tags, **metadata):
    """Log with optional tags and metadata."""
    print(f"[{level}] {message}")
    if tags:
        print(f"  Tags: {', '.join(tags)}")
    if metadata:
        for key, value in metadata.items():
            print(f"  {key}: {value}")
    print()

def demonstrate_order(required, *args, kw_only, **kwargs):
    """Show the required parameter order."""
    print(f"required: {required}")
    print(f"*args: {args}")
    print(f"kw_only: {kw_only}")
    print(f"**kwargs: {kwargs}")

def catch_all(*args, **kwargs):
    """Accept literally anything."""
    print(f"Positional ({len(args)}): {args}")
    print(f"Keyword ({len(kwargs)}): {kwargs}")

if __name__ == "__main__":
    main()
  1. def main():

    1def main():2    print("=== Combining *args and **kwargs ===\n")3    4    # Both together  #?combined5    log("INFO", "User logged in", user="Alice", ip="192.168.1.1")6    log("ERROR", "Connection failed", "timeout", retries=3)
    output=== Combining *args and **kwargs ===
  2. def log(level, message, *tags, **metadata): #?signature

    pass 1 of 3
    16def log(levelINFO, messageUser logged in, *tags(), **metadata):  #?signature17    """Log with optional tags and metadata."""18    print(f"[{levelINFO}] {messageUser logged in}")19    if tags:
    output[INFO] User logged in
    All 3 passes — pass 1 is the card above
    passlevelmessagetagsmetadatarequiredargskw_onlykwargs
    1INFOUser logged in(){'user': 'Alice', 'ip': '192.168.1.1'}
    2ERRORConnection failed('timeout',){'retries': 3}
    3DEBUGProcessing()required('extra1', 'extra2')value{'opt1': 'a', 'opt2': 'b'}
  3. if metadata:

    pass 1 of 2
    20    print(f"  Tags: {', '.join(tags)}")21if metadata{'user': 'Alice', 'ip': '192.168.1.1'}:22    for key, value in metadata.items():23        print(f"  {key}: {value}")
  4. for key, value in metadata.items():

    pass 1 of 3
    21if metadata:22    for keyuser, valueAlice in metadata{'user': 'Alice', 'ip': '192.168.1.1'}.items():23        print(f"  {keyuser}: {valueAlice}")24print()
    output  user: Alice
    All 3 passes — pass 1 is the card above
    passkeyvaluemetadata
    1userAlice{'user': 'Alice', 'ip': '192.168.1.1'}
    2ip192.168.1.1{'user': 'Alice', 'ip': '192.168.1.1'}
    3retries3{'retries': 3}
  5. print()

    4    # Both together  #?combined5    log("INFO", "User logged in", user="Alice", ip="192.168.1.1")6    log("ERROR", "Connection failed", "timeout", retries=3)7    log("DEBUG", "Processing")  # Just message8    9    print("\n=== Full Signature Order ===")  #?order10    demonstrate_order("required", "extra1", "extra2", 11                     kw_only="value", opt1="a", opt2="b")12    13    print("\n=== Catch-All Function ===")  #?catchall14    catch_all(1, 2, 3, name="test", flag=True)1516def log(level, message, *tags, **metadata):  #?signature17    """Log with optional tags and metadata."""18    print(f"[{level}] {message}")19    if tags:20        print(f"  Tags: {', '.join(tags)}")21    if metadata:22        for key, value in metadata.items():23            print(f"  {key}: {value}")24    print()
  6. if tags:

    18print(f"[{level}] {message}")19if tags('timeout',):20    print(f"  Tags: {', '.join(tags('timeout',))}")21if metadata:
    output  Tags: timeout
  7. if metadata:

    pass 2 of 2
    20    print(f"  Tags: {', '.join(tags)}")21if metadata{'retries': 3}:22    for key, value in metadata.items():23        print(f"  {key}: {value}")
  8. print()

    5    log("INFO", "User logged in", user="Alice", ip="192.168.1.1")6    log("ERROR", "Connection failed", "timeout", retries=3)7    log("DEBUG", "Processing")  # Just message8    9    print("\n=== Full Signature Order ===")  #?order10    demonstrate_order("required", "extra1", "extra2", 11                     kw_only="value", opt1="a", opt2="b")12    13    print("\n=== Catch-All Function ===")  #?catchall14    catch_all(1, 2, 3, name="test", flag=True)1516def log(level, message, *tags, **metadata):  #?signature17    """Log with optional tags and metadata."""18    print(f"[{level}] {message}")19    if tags:20        print(f"  Tags: {', '.join(tags)}")21    if metadata:22        for key, value in metadata.items():23            print(f"  {key}: {value}")24    print()
  9. def demonstrate_order(required, *args, kw_only, **kwargs): #?fullorde…

    9    print("\n=== Full Signature Order ===")  #?order10    demonstrate_order("required", "extra1", "extra2", 11                     kw_only="value", opt1="a", opt2="b")12    13    print("\n=== Catch-All Function ===")  #?catchall14    catch_all(1, 2, 3, name="test", flag=True)1516def log(level, message, *tags, **metadata):  #?signature17    """Log with optional tags and metadata."""18    print(f"[{level}] {message}")19    if tags:20        print(f"  Tags: {', '.join(tags)}")21    if metadata:22        for key, value in metadata.items():23            print(f"  {key}: {value}")24    print()2526def demonstrate_order(requiredrequired, *args('extra1', 'extra2'), kw_only, **kwargs):  #?fullorder27    """Show the required parameter order."""28    print(f"required: {requiredrequired}")29    print(f"*args: {args('extra1', 'extra2')}")30    print(f"kw_only: {kw_onlyvalue}")31    print(f"**kwargs: {kwargs{'opt1': 'a', 'opt2': 'b'}}")
    outputrequired: required
    *args: ('extra1', 'extra2')
    kw_only: value
    **kwargs: {'opt1': 'a', 'opt2': 'b'}
    
    === Catch-All Function ===
  10. def catch_all(*args, **kwargs): #?catchall_fn

    13    print("\n=== Catch-All Function ===")  #?catchall14    catch_all(1, 2, 3, name="test", flag=True)1516def log(level, message, *tags, **metadata):  #?signature17    """Log with optional tags and metadata."""18    print(f"[{level}] {message}")19    if tags:20        print(f"  Tags: {', '.join(tags)}")21    if metadata:22        for key, value in metadata.items():23            print(f"  {key}: {value}")24    print()2526def demonstrate_order(required, *args, kw_only, **kwargs):  #?fullorder27    """Show the required parameter order."""28    print(f"required: {required}")29    print(f"*args: {args}")30    print(f"kw_only: {kw_only}")31    print(f"**kwargs: {kwargs}")3233def catch_all(*args(1, 2, 3), **kwargs):  #?catchall_fn34    """Accept literally anything."""35    print(f"Positional ({len(args(1, 2, 3))}): {args}")36    print(f"Keyword ({len(kwargs{'name': 'test', 'flag': True})}): {kwargs}")
    outputPositional (3): (1, 2, 3)
    Keyword (2): {'name': 'test', 'flag': True}
  11. main()

    38if __name__ == "__main__":39    main()40#@help combined

Order matters: regular params, *args, keyword-only params, **kwargs.

Unpack into function calls

Use * and ** to expand sequences and dicts into arguments.

example
unpacking.py
Replay: real traced execution (multi-file project)
def main():
    print("=== Unpacking: * and ** in Function Calls ===\n")

    # Unpack list/tuple into positional args
    numbers = [10, 20, 30]
    print(f"numbers = {numbers}")
    print(f"add(numbers) would fail - it's one arg")
    print(f"add(*numbers) = {add(*numbers)}")  # Unpacks!

    print("\n=== Unpack Dict into Keyword Args ===")
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
    print(f"config = {config}")
    connect(**config)  # Same as connect(host='...', port=..., debug=...)

    print("\n=== Combined Unpacking ===")
    args = [5, 3]
    kwargs = {'operation': 'multiply'}
    calculate(*args, **kwargs)

    print("\n=== Range Example ===")
    # start, stop, step
    bounds = (1, 10, 2)
    print(f"bounds = {bounds}")
    print(f"list(range(*bounds)) = {list(range(*bounds))}")

    print("\n=== Merge Dicts with ** ===")
    defaults = {'color': 'blue', 'size': 'medium'}
    overrides = {'size': 'large', 'style': 'bold'}
    merged = {**defaults, **overrides}
    print(f"defaults: {defaults}")
    print(f"overrides: {overrides}")
    print(f"merged: {merged}")

def add(a, b, c):
    """Add three numbers."""
    return a + b + c

def connect(host, port, debug=False):
    """Simulate connection."""
    print(f"Connecting to {host}:{port} (debug={debug})")

def calculate(x, y, operation='add'):
    """Perform calculation."""
    if operation == 'add':
        print(f"{x} + {y} = {x + y}")
    elif operation == 'multiply':
        print(f"{x} * {y} = {x * y}")

if __name__ == "__main__":
    main()
def main():
    print("=== Unpacking: * and ** in Function Calls ===\n")

    # Unpack list/tuple into positional args
    numbers = [1, 2, 3]
    print(f"numbers = {numbers}")
    print(f"add(numbers) would fail - it's one arg")
    print(f"add(*numbers) = {add(*numbers)}")  # Unpacks!

    print("\n=== Unpack Dict into Keyword Args ===")
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
    print(f"config = {config}")
    connect(**config)  # Same as connect(host='...', port=..., debug=...)

    print("\n=== Combined Unpacking ===")
    args = [5, 3]
    kwargs = {'operation': 'multiply'}
    calculate(*args, **kwargs)

    print("\n=== Range Example ===")
    # start, stop, step
    bounds = (1, 10, 2)
    print(f"bounds = {bounds}")
    print(f"list(range(*bounds)) = {list(range(*bounds))}")

    print("\n=== Merge Dicts with ** ===")
    defaults = {'color': 'blue', 'size': 'medium'}
    overrides = {'size': 'large', 'style': 'bold'}
    merged = {**defaults, **overrides}
    print(f"defaults: {defaults}")
    print(f"overrides: {overrides}")
    print(f"merged: {merged}")

def add(a, b, c):
    """Add three numbers."""
    return a + b + c

def connect(host, port, debug=False):
    """Simulate connection."""
    print(f"Connecting to {host}:{port} (debug={debug})")

def calculate(x, y, operation='add'):
    """Perform calculation."""
    if operation == 'add':
        print(f"{x} + {y} = {x + y}")
    elif operation == 'multiply':
        print(f"{x} * {y} = {x * y}")

if __name__ == "__main__":
    main()
def main():
    print("=== Unpacking: * and ** in Function Calls ===\n")

    # Unpack list/tuple into positional args
    numbers = [5, 10, 15]
    print(f"numbers = {numbers}")
    print(f"add(numbers) would fail - it's one arg")
    print(f"add(*numbers) = {add(*numbers)}")  # Unpacks!

    print("\n=== Unpack Dict into Keyword Args ===")
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
    print(f"config = {config}")
    connect(**config)  # Same as connect(host='...', port=..., debug=...)

    print("\n=== Combined Unpacking ===")
    args = [5, 3]
    kwargs = {'operation': 'multiply'}
    calculate(*args, **kwargs)

    print("\n=== Range Example ===")
    # start, stop, step
    bounds = (1, 10, 2)
    print(f"bounds = {bounds}")
    print(f"list(range(*bounds)) = {list(range(*bounds))}")

    print("\n=== Merge Dicts with ** ===")
    defaults = {'color': 'blue', 'size': 'medium'}
    overrides = {'size': 'large', 'style': 'bold'}
    merged = {**defaults, **overrides}
    print(f"defaults: {defaults}")
    print(f"overrides: {overrides}")
    print(f"merged: {merged}")

def add(a, b, c):
    """Add three numbers."""
    return a + b + c

def connect(host, port, debug=False):
    """Simulate connection."""
    print(f"Connecting to {host}:{port} (debug={debug})")

def calculate(x, y, operation='add'):
    """Perform calculation."""
    if operation == 'add':
        print(f"{x} + {y} = {x + y}")
    elif operation == 'multiply':
        print(f"{x} * {y} = {x * y}")

if __name__ == "__main__":
    main()
def main():
    print("=== Unpacking: * and ** in Function Calls ===\n")

    # Unpack list/tuple into positional args
    numbers = [10, 20, 30]
    print(f"numbers = {numbers}")
    print(f"add(numbers) would fail - it's one arg")
    print(f"add(*numbers) = {add(*numbers)}")  # Unpacks!

    print("\n=== Unpack Dict into Keyword Args ===")
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
    print(f"config = {config}")
    connect(**config)  # Same as connect(host='...', port=..., debug=...)

    print("\n=== Combined Unpacking ===")
    args = [5, 3]
    kwargs = {'operation': 'multiply'}
    calculate(*args, **kwargs)

    print("\n=== Range Example ===")
    # start, stop, step
    bounds = (0, 12, 3)
    print(f"bounds = {bounds}")
    print(f"list(range(*bounds)) = {list(range(*bounds))}")

    print("\n=== Merge Dicts with ** ===")
    defaults = {'color': 'blue', 'size': 'medium'}
    overrides = {'size': 'large', 'style': 'bold'}
    merged = {**defaults, **overrides}
    print(f"defaults: {defaults}")
    print(f"overrides: {overrides}")
    print(f"merged: {merged}")

def add(a, b, c):
    """Add three numbers."""
    return a + b + c

def connect(host, port, debug=False):
    """Simulate connection."""
    print(f"Connecting to {host}:{port} (debug={debug})")

def calculate(x, y, operation='add'):
    """Perform calculation."""
    if operation == 'add':
        print(f"{x} + {y} = {x + y}")
    elif operation == 'multiply':
        print(f"{x} * {y} = {x * y}")

if __name__ == "__main__":
    main()
def main():
    print("=== Unpacking: * and ** in Function Calls ===\n")

    # Unpack list/tuple into positional args
    numbers = [10, 20, 30]
    print(f"numbers = {numbers}")
    print(f"add(numbers) would fail - it's one arg")
    print(f"add(*numbers) = {add(*numbers)}")  # Unpacks!

    print("\n=== Unpack Dict into Keyword Args ===")
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
    print(f"config = {config}")
    connect(**config)  # Same as connect(host='...', port=..., debug=...)

    print("\n=== Combined Unpacking ===")
    args = [5, 3]
    kwargs = {'operation': 'multiply'}
    calculate(*args, **kwargs)

    print("\n=== Range Example ===")
    # start, stop, step
    bounds = (2, 9, 2)
    print(f"bounds = {bounds}")
    print(f"list(range(*bounds)) = {list(range(*bounds))}")

    print("\n=== Merge Dicts with ** ===")
    defaults = {'color': 'blue', 'size': 'medium'}
    overrides = {'size': 'large', 'style': 'bold'}
    merged = {**defaults, **overrides}
    print(f"defaults: {defaults}")
    print(f"overrides: {overrides}")
    print(f"merged: {merged}")

def add(a, b, c):
    """Add three numbers."""
    return a + b + c

def connect(host, port, debug=False):
    """Simulate connection."""
    print(f"Connecting to {host}:{port} (debug={debug})")

def calculate(x, y, operation='add'):
    """Perform calculation."""
    if operation == 'add':
        print(f"{x} + {y} = {x + y}")
    elif operation == 'multiply':
        print(f"{x} * {y} = {x * y}")

if __name__ == "__main__":
    main()
  1. numbers ← [10, 20, 30]

    1#@var=default,advanced2def main():3    print("=== Unpacking: * and ** in Function Calls ===\n")4    5    # Unpack list/tuple into positional args  #?unpack_list6    numbers→ [10, 20, 30] = [10, 20, 30]  #@numbers=[1, 2, 3], [5, 10, 15]7    print(f"numbers = {numbers[10, 20, 30]}")8    print(f"add(numbers) would fail - it's one arg")9    print(f"add(*numbers) = {add(*numbers[10, 20, 30])}")  # Unpacks!
    output=== Unpacking: * and ** in Function Calls ===
    numbers = [10, 20, 30]
    add(numbers) would fail - it's one arg
  2. def add(a, b, c):

    37def add(a10, b20, c30):38    """Add three numbers."""39    return a10 + b20 + c30
  3. config ← {'host': 'localhost', 'port': 8080, 'debug': True}

    8print(f"add(numbers) would fail - it's one arg")9print(f"add(*numbers) = {add(*numbers[10, 20, 30])}")  # Unpacks!1011print("\n=== Unpack Dict into Keyword Args ===")  #?unpack_dict12config→ {'host': 'localhost', 'port': 8080, 'debug': True} = {'host': 'localhost', 'port': 8080, 'debug': True}13print(f"config = {config{'host': 'localhost', 'port': 8080, 'debug': True}}")14connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)
    outputadd(*numbers) = 60
    
    === Unpack Dict into Keyword Args ===
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
  4. args ← [5, 3], kwargs ← {'operation': 'multiply'}

    13    print(f"config = {config}")14    connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)15    16    print("\n=== Combined Unpacking ===")  #?combined17    args→ [5, 3] = [5, 3]18    kwargs→ {'operation': 'multiply'} = {'operation': 'multiply'}19    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})20    21    print("\n=== Range Example ===")  #?range22    # start, stop, step23    bounds = (1, 10, 2)  #@bounds=(0, 12, 3), (2, 9, 2)24    print(f"bounds = {bounds}")25    print(f"list(range(*bounds)) = {list(range(*bounds))}")26    27    #@var=_,!28    print("\n=== Merge Dicts with ** ===")29    defaults = {'color': 'blue', 'size': 'medium'}30    overrides = {'size': 'large', 'style': 'bold'}31    merged = {**defaults, **overrides}  #?merge32    print(f"defaults: {defaults}")33    print(f"overrides: {overrides}")34    print(f"merged: {merged}")35    #@var=_,!3637def add(a, b, c):38    """Add three numbers."""39    return a + b + c4041def connect(hostlocalhost, port8080, debugTrue=FalseFalse):  #?connect42    """Simulate connection."""43    print(f"Connecting to {hostlocalhost}:{port8080} (debug={debugTrue})")
    outputConnecting to localhost:8080 (debug=True)
    
    === Combined Unpacking ===
  5. def calculate(x, y, operation='add'):

    45def calculate(x5, y3, operationmultiply='add'):46    """Perform calculation."""47    if operation == 'add':
  6. bounds ← (1, 10, 2), defaults ← {'color': 'blue', 'size': 'medium'}

    18    kwargs = {'operation': 'multiply'}19    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})20    21    print("\n=== Range Example ===")  #?range22    # start, stop, step23    bounds→ (1, 10, 2) = (1, 10, 2)  #@bounds=(0, 12, 3), (2, 9, 2)24    print(f"bounds = {bounds(1, 10, 2)}")25    print(f"list(range(*bounds)) = {list(range(*bounds(1, 10, 2)))}")26    27    #@var=_,!28    print("\n=== Merge Dicts with ** ===")29    defaults→ {'color': 'blue', 'size': 'medium'} = {'color': 'blue', 'size': 'medium'}30    overrides→ {'size': 'large', 'style': 'bold'} = {'size': 'large', 'style': 'bold'}31    merged→ {'color': 'blue', 'size': 'large', 'style': 'bold'} = {**defaults{'color': 'blue', 'size': 'medium'}, **overrides{'size': 'large', 'style': 'bold'}}  #?merge32    print(f"defaults: {defaults{'color': 'blue', 'size': 'medium'}}")33    print(f"overrides: {overrides{'size': 'large', 'style': 'bold'}}")34    print(f"merged: {merged{'color': 'blue', 'size': 'large', 'style': 'bold'}}")35    #@var=_,!3637def add(a, b, c):38    """Add three numbers."""39    return a + b + c4041def connect(host, port, debug=False):  #?connect42    """Simulate connection."""43    print(f"Connecting to {host}:{port} (debug={debug})")4445def calculate(x, y, operation='add'):46    """Perform calculation."""47    if operation == 'add':48        print(f"{x} + {y} = {x + y}")49    elif operationmultiply == 'multiply':50        print(f"{x5} * {y3} = {x * y}")
    output5 * 3 = 15
    
    === Range Example ===
    bounds = (1, 10, 2)
    list(range(*bounds)) = [1, 3, 5, 7, 9]
    
    === Merge Dicts with ** ===
    defaults: {'color': 'blue', 'size': 'medium'}
    overrides: {'size': 'large', 'style': 'bold'}
    merged: {'color': 'blue', 'size': 'large', 'style': 'bold'}
  7. main()

    52if __name__ == "__main__":53    main()54#@help unpack_list
  1. numbers ← [1, 2, 3]

    1def main():2    print("=== Unpacking: * and ** in Function Calls ===\n")3    4    # Unpack list/tuple into positional args5    numbers→ [1, 2, 3] = [1, 2, 3]6    print(f"numbers = {numbers[1, 2, 3]}")7    print(f"add(numbers) would fail - it's one arg")8    print(f"add(*numbers) = {add(*numbers[1, 2, 3])}")  # Unpacks!
    output=== Unpacking: * and ** in Function Calls ===
    numbers = [1, 2, 3]
    add(numbers) would fail - it's one arg
  2. def add(a, b, c):

    34def add(a1, b2, c3):35    """Add three numbers."""36    return a1 + b2 + c3
  3. config ← {'host': 'localhost', 'port': 8080, 'debug': True}

    7print(f"add(numbers) would fail - it's one arg")8print(f"add(*numbers) = {add(*numbers[1, 2, 3])}")  # Unpacks!910print("\n=== Unpack Dict into Keyword Args ===")11config→ {'host': 'localhost', 'port': 8080, 'debug': True} = {'host': 'localhost', 'port': 8080, 'debug': True}12print(f"config = {config{'host': 'localhost', 'port': 8080, 'debug': True}}")13connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)
    outputadd(*numbers) = 6
    
    === Unpack Dict into Keyword Args ===
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
  4. args ← [5, 3], kwargs ← {'operation': 'multiply'}

    12    print(f"config = {config}")13    connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)14    15    print("\n=== Combined Unpacking ===")16    args→ [5, 3] = [5, 3]17    kwargs→ {'operation': 'multiply'} = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds = (1, 10, 2)23    print(f"bounds = {bounds}")24    print(f"list(range(*bounds)) = {list(range(*bounds))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults = {'color': 'blue', 'size': 'medium'}28    overrides = {'size': 'large', 'style': 'bold'}29    merged = {**defaults, **overrides}30    print(f"defaults: {defaults}")31    print(f"overrides: {overrides}")32    print(f"merged: {merged}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(hostlocalhost, port8080, debugTrue=FalseFalse):39    """Simulate connection."""40    print(f"Connecting to {hostlocalhost}:{port8080} (debug={debugTrue})")
    outputConnecting to localhost:8080 (debug=True)
    
    === Combined Unpacking ===
  5. def calculate(x, y, operation='add'):

    42def calculate(x5, y3, operationmultiply='add'):43    """Perform calculation."""44    if operation == 'add':
  6. bounds ← (1, 10, 2), defaults ← {'color': 'blue', 'size': 'medium'}

    17    kwargs = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds→ (1, 10, 2) = (1, 10, 2)23    print(f"bounds = {bounds(1, 10, 2)}")24    print(f"list(range(*bounds)) = {list(range(*bounds(1, 10, 2)))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults→ {'color': 'blue', 'size': 'medium'} = {'color': 'blue', 'size': 'medium'}28    overrides→ {'size': 'large', 'style': 'bold'} = {'size': 'large', 'style': 'bold'}29    merged→ {'color': 'blue', 'size': 'large', 'style': 'bold'} = {**defaults{'color': 'blue', 'size': 'medium'}, **overrides{'size': 'large', 'style': 'bold'}}30    print(f"defaults: {defaults{'color': 'blue', 'size': 'medium'}}")31    print(f"overrides: {overrides{'size': 'large', 'style': 'bold'}}")32    print(f"merged: {merged{'color': 'blue', 'size': 'large', 'style': 'bold'}}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(host, port, debug=False):39    """Simulate connection."""40    print(f"Connecting to {host}:{port} (debug={debug})")4142def calculate(x, y, operation='add'):43    """Perform calculation."""44    if operation == 'add':45        print(f"{x} + {y} = {x + y}")46    elif operationmultiply == 'multiply':47        print(f"{x5} * {y3} = {x * y}")
    output5 * 3 = 15
    
    === Range Example ===
    bounds = (1, 10, 2)
    list(range(*bounds)) = [1, 3, 5, 7, 9]
    
    === Merge Dicts with ** ===
    defaults: {'color': 'blue', 'size': 'medium'}
    overrides: {'size': 'large', 'style': 'bold'}
    merged: {'color': 'blue', 'size': 'large', 'style': 'bold'}
  7. main()

    49if __name__ == "__main__":50    main()
  1. numbers ← [5, 10, 15]

    1def main():2    print("=== Unpacking: * and ** in Function Calls ===\n")3    4    # Unpack list/tuple into positional args5    numbers→ [5, 10, 15] = [5, 10, 15]6    print(f"numbers = {numbers[5, 10, 15]}")7    print(f"add(numbers) would fail - it's one arg")8    print(f"add(*numbers) = {add(*numbers[5, 10, 15])}")  # Unpacks!
    output=== Unpacking: * and ** in Function Calls ===
    numbers = [5, 10, 15]
    add(numbers) would fail - it's one arg
  2. def add(a, b, c):

    34def add(a5, b10, c15):35    """Add three numbers."""36    return a5 + b10 + c15
  3. config ← {'host': 'localhost', 'port': 8080, 'debug': True}

    7print(f"add(numbers) would fail - it's one arg")8print(f"add(*numbers) = {add(*numbers[5, 10, 15])}")  # Unpacks!910print("\n=== Unpack Dict into Keyword Args ===")11config→ {'host': 'localhost', 'port': 8080, 'debug': True} = {'host': 'localhost', 'port': 8080, 'debug': True}12print(f"config = {config{'host': 'localhost', 'port': 8080, 'debug': True}}")13connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)
    outputadd(*numbers) = 30
    
    === Unpack Dict into Keyword Args ===
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
  4. args ← [5, 3], kwargs ← {'operation': 'multiply'}

    12    print(f"config = {config}")13    connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)14    15    print("\n=== Combined Unpacking ===")16    args→ [5, 3] = [5, 3]17    kwargs→ {'operation': 'multiply'} = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds = (1, 10, 2)23    print(f"bounds = {bounds}")24    print(f"list(range(*bounds)) = {list(range(*bounds))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults = {'color': 'blue', 'size': 'medium'}28    overrides = {'size': 'large', 'style': 'bold'}29    merged = {**defaults, **overrides}30    print(f"defaults: {defaults}")31    print(f"overrides: {overrides}")32    print(f"merged: {merged}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(hostlocalhost, port8080, debugTrue=FalseFalse):39    """Simulate connection."""40    print(f"Connecting to {hostlocalhost}:{port8080} (debug={debugTrue})")
    outputConnecting to localhost:8080 (debug=True)
    
    === Combined Unpacking ===
  5. def calculate(x, y, operation='add'):

    42def calculate(x5, y3, operationmultiply='add'):43    """Perform calculation."""44    if operation == 'add':
  6. bounds ← (1, 10, 2), defaults ← {'color': 'blue', 'size': 'medium'}

    17    kwargs = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds→ (1, 10, 2) = (1, 10, 2)23    print(f"bounds = {bounds(1, 10, 2)}")24    print(f"list(range(*bounds)) = {list(range(*bounds(1, 10, 2)))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults→ {'color': 'blue', 'size': 'medium'} = {'color': 'blue', 'size': 'medium'}28    overrides→ {'size': 'large', 'style': 'bold'} = {'size': 'large', 'style': 'bold'}29    merged→ {'color': 'blue', 'size': 'large', 'style': 'bold'} = {**defaults{'color': 'blue', 'size': 'medium'}, **overrides{'size': 'large', 'style': 'bold'}}30    print(f"defaults: {defaults{'color': 'blue', 'size': 'medium'}}")31    print(f"overrides: {overrides{'size': 'large', 'style': 'bold'}}")32    print(f"merged: {merged{'color': 'blue', 'size': 'large', 'style': 'bold'}}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(host, port, debug=False):39    """Simulate connection."""40    print(f"Connecting to {host}:{port} (debug={debug})")4142def calculate(x, y, operation='add'):43    """Perform calculation."""44    if operation == 'add':45        print(f"{x} + {y} = {x + y}")46    elif operationmultiply == 'multiply':47        print(f"{x5} * {y3} = {x * y}")
    output5 * 3 = 15
    
    === Range Example ===
    bounds = (1, 10, 2)
    list(range(*bounds)) = [1, 3, 5, 7, 9]
    
    === Merge Dicts with ** ===
    defaults: {'color': 'blue', 'size': 'medium'}
    overrides: {'size': 'large', 'style': 'bold'}
    merged: {'color': 'blue', 'size': 'large', 'style': 'bold'}
  7. main()

    49if __name__ == "__main__":50    main()
  1. numbers ← [10, 20, 30]

    1def main():2    print("=== Unpacking: * and ** in Function Calls ===\n")3    4    # Unpack list/tuple into positional args5    numbers→ [10, 20, 30] = [10, 20, 30]6    print(f"numbers = {numbers[10, 20, 30]}")7    print(f"add(numbers) would fail - it's one arg")8    print(f"add(*numbers) = {add(*numbers[10, 20, 30])}")  # Unpacks!
    output=== Unpacking: * and ** in Function Calls ===
    numbers = [10, 20, 30]
    add(numbers) would fail - it's one arg
  2. def add(a, b, c):

    34def add(a10, b20, c30):35    """Add three numbers."""36    return a10 + b20 + c30
  3. config ← {'host': 'localhost', 'port': 8080, 'debug': True}

    7print(f"add(numbers) would fail - it's one arg")8print(f"add(*numbers) = {add(*numbers[10, 20, 30])}")  # Unpacks!910print("\n=== Unpack Dict into Keyword Args ===")11config→ {'host': 'localhost', 'port': 8080, 'debug': True} = {'host': 'localhost', 'port': 8080, 'debug': True}12print(f"config = {config{'host': 'localhost', 'port': 8080, 'debug': True}}")13connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)
    outputadd(*numbers) = 60
    
    === Unpack Dict into Keyword Args ===
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
  4. args ← [5, 3], kwargs ← {'operation': 'multiply'}

    12    print(f"config = {config}")13    connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)14    15    print("\n=== Combined Unpacking ===")16    args→ [5, 3] = [5, 3]17    kwargs→ {'operation': 'multiply'} = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds = (0, 12, 3)23    print(f"bounds = {bounds}")24    print(f"list(range(*bounds)) = {list(range(*bounds))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults = {'color': 'blue', 'size': 'medium'}28    overrides = {'size': 'large', 'style': 'bold'}29    merged = {**defaults, **overrides}30    print(f"defaults: {defaults}")31    print(f"overrides: {overrides}")32    print(f"merged: {merged}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(hostlocalhost, port8080, debugTrue=FalseFalse):39    """Simulate connection."""40    print(f"Connecting to {hostlocalhost}:{port8080} (debug={debugTrue})")
    outputConnecting to localhost:8080 (debug=True)
    
    === Combined Unpacking ===
  5. def calculate(x, y, operation='add'):

    42def calculate(x5, y3, operationmultiply='add'):43    """Perform calculation."""44    if operation == 'add':
  6. bounds ← (0, 12, 3), defaults ← {'color': 'blue', 'size': 'medium'}

    17    kwargs = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds→ (0, 12, 3) = (0, 12, 3)23    print(f"bounds = {bounds(0, 12, 3)}")24    print(f"list(range(*bounds)) = {list(range(*bounds(0, 12, 3)))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults→ {'color': 'blue', 'size': 'medium'} = {'color': 'blue', 'size': 'medium'}28    overrides→ {'size': 'large', 'style': 'bold'} = {'size': 'large', 'style': 'bold'}29    merged→ {'color': 'blue', 'size': 'large', 'style': 'bold'} = {**defaults{'color': 'blue', 'size': 'medium'}, **overrides{'size': 'large', 'style': 'bold'}}30    print(f"defaults: {defaults{'color': 'blue', 'size': 'medium'}}")31    print(f"overrides: {overrides{'size': 'large', 'style': 'bold'}}")32    print(f"merged: {merged{'color': 'blue', 'size': 'large', 'style': 'bold'}}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(host, port, debug=False):39    """Simulate connection."""40    print(f"Connecting to {host}:{port} (debug={debug})")4142def calculate(x, y, operation='add'):43    """Perform calculation."""44    if operation == 'add':45        print(f"{x} + {y} = {x + y}")46    elif operationmultiply == 'multiply':47        print(f"{x5} * {y3} = {x * y}")
    output5 * 3 = 15
    
    === Range Example ===
    bounds = (0, 12, 3)
    list(range(*bounds)) = [0, 3, 6, 9]
    
    === Merge Dicts with ** ===
    defaults: {'color': 'blue', 'size': 'medium'}
    overrides: {'size': 'large', 'style': 'bold'}
    merged: {'color': 'blue', 'size': 'large', 'style': 'bold'}
  7. main()

    49if __name__ == "__main__":50    main()
  1. numbers ← [10, 20, 30]

    1def main():2    print("=== Unpacking: * and ** in Function Calls ===\n")3    4    # Unpack list/tuple into positional args5    numbers→ [10, 20, 30] = [10, 20, 30]6    print(f"numbers = {numbers[10, 20, 30]}")7    print(f"add(numbers) would fail - it's one arg")8    print(f"add(*numbers) = {add(*numbers[10, 20, 30])}")  # Unpacks!
    output=== Unpacking: * and ** in Function Calls ===
    numbers = [10, 20, 30]
    add(numbers) would fail - it's one arg
  2. def add(a, b, c):

    34def add(a10, b20, c30):35    """Add three numbers."""36    return a10 + b20 + c30
  3. config ← {'host': 'localhost', 'port': 8080, 'debug': True}

    7print(f"add(numbers) would fail - it's one arg")8print(f"add(*numbers) = {add(*numbers[10, 20, 30])}")  # Unpacks!910print("\n=== Unpack Dict into Keyword Args ===")11config→ {'host': 'localhost', 'port': 8080, 'debug': True} = {'host': 'localhost', 'port': 8080, 'debug': True}12print(f"config = {config{'host': 'localhost', 'port': 8080, 'debug': True}}")13connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)
    outputadd(*numbers) = 60
    
    === Unpack Dict into Keyword Args ===
    config = {'host': 'localhost', 'port': 8080, 'debug': True}
  4. args ← [5, 3], kwargs ← {'operation': 'multiply'}

    12    print(f"config = {config}")13    connect(**config{'host': 'localhost', 'port': 8080, 'debug': True})  # Same as connect(host='...', port=..., debug=...)14    15    print("\n=== Combined Unpacking ===")16    args→ [5, 3] = [5, 3]17    kwargs→ {'operation': 'multiply'} = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds = (2, 9, 2)23    print(f"bounds = {bounds}")24    print(f"list(range(*bounds)) = {list(range(*bounds))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults = {'color': 'blue', 'size': 'medium'}28    overrides = {'size': 'large', 'style': 'bold'}29    merged = {**defaults, **overrides}30    print(f"defaults: {defaults}")31    print(f"overrides: {overrides}")32    print(f"merged: {merged}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(hostlocalhost, port8080, debugTrue=FalseFalse):39    """Simulate connection."""40    print(f"Connecting to {hostlocalhost}:{port8080} (debug={debugTrue})")
    outputConnecting to localhost:8080 (debug=True)
    
    === Combined Unpacking ===
  5. def calculate(x, y, operation='add'):

    42def calculate(x5, y3, operationmultiply='add'):43    """Perform calculation."""44    if operation == 'add':
  6. bounds ← (2, 9, 2), defaults ← {'color': 'blue', 'size': 'medium'}

    17    kwargs = {'operation': 'multiply'}18    calculate(*args[5, 3], **kwargs{'operation': 'multiply'})19    20    print("\n=== Range Example ===")21    # start, stop, step22    bounds→ (2, 9, 2) = (2, 9, 2)23    print(f"bounds = {bounds(2, 9, 2)}")24    print(f"list(range(*bounds)) = {list(range(*bounds(2, 9, 2)))}")25    26    print("\n=== Merge Dicts with ** ===")27    defaults→ {'color': 'blue', 'size': 'medium'} = {'color': 'blue', 'size': 'medium'}28    overrides→ {'size': 'large', 'style': 'bold'} = {'size': 'large', 'style': 'bold'}29    merged→ {'color': 'blue', 'size': 'large', 'style': 'bold'} = {**defaults{'color': 'blue', 'size': 'medium'}, **overrides{'size': 'large', 'style': 'bold'}}30    print(f"defaults: {defaults{'color': 'blue', 'size': 'medium'}}")31    print(f"overrides: {overrides{'size': 'large', 'style': 'bold'}}")32    print(f"merged: {merged{'color': 'blue', 'size': 'large', 'style': 'bold'}}")3334def add(a, b, c):35    """Add three numbers."""36    return a + b + c3738def connect(host, port, debug=False):39    """Simulate connection."""40    print(f"Connecting to {host}:{port} (debug={debug})")4142def calculate(x, y, operation='add'):43    """Perform calculation."""44    if operation == 'add':45        print(f"{x} + {y} = {x + y}")46    elif operationmultiply == 'multiply':47        print(f"{x5} * {y3} = {x * y}")
    output5 * 3 = 15
    
    === Range Example ===
    bounds = (2, 9, 2)
    list(range(*bounds)) = [2, 4, 6, 8]
    
    === Merge Dicts with ** ===
    defaults: {'color': 'blue', 'size': 'medium'}
    overrides: {'size': 'large', 'style': 'bold'}
    merged: {'color': 'blue', 'size': 'large', 'style': 'bold'}
  7. main()

    49if __name__ == "__main__":50    main()

func(*list) unpacks list as positional args. func(**dict) unpacks as keyword args.

unpacking Expand collections into arguments: `f(*[1,2])` is `f(1,2)`.

Forward arguments to other functions

Pass received arguments to another function unchanged.

forwarding.py
Replay: real traced execution (multi-file project)
def main():
    print("=== Forwarding Arguments ===\n")

    # Wrapper forwards to inner function
    print("Wrapper forwarding:")
    wrapper_example(1, 2, 3, name="test", flag=True)

    print("\n=== Logging Wrapper ===")
    logged_add(10, 20)
    logged_multiply(5, 3, verbose=True)

    print("\n=== Super() Forwarding ===")
    fancy = FancyButton("Click Me", color="blue", size="large")

def wrapper_example(*args, **kwargs):
    """Wrapper that forwards everything."""
    print(f"  Wrapper received: args={args}, kwargs={kwargs}")
    print("  Forwarding to inner function...")
    inner_function(*args, **kwargs)

def inner_function(*args, **kwargs):
    print(f"  Inner got: args={args}, kwargs={kwargs}")

# Logging wrapper pattern
def logged_add(a, b):
    print(f"  [LOG] Calling add({a}, {b})")
    result = a + b
    print(f"  [LOG] Result: {result}")
    return result

def logged_multiply(a, b, verbose=False):
    if verbose:
        print(f"  [VERBOSE] multiply called with a={a}, b={b}")
    result = a * b
    print(f"  [LOG] multiply result: {result}")
    return result

# Class inheritance forwarding
class Button:
    def __init__(self, text, **options):
        self.text = text
        self.options = options
        print(f"  Button created: '{text}' with {options}")

class FancyButton(Button):
    def __init__(self, text, **options):
        # Add default options
        options.setdefault('border', True)
        # Forward to parent
        super().__init__(text, **options)
        print("  (FancyButton enhancements applied)")

if __name__ == "__main__":
    main()
  1. def main():

    1def main():2    print("=== Forwarding Arguments ===\n")3    4    # Wrapper forwards to inner function  #?forward5    print("Wrapper forwarding:")6    wrapper_example(1, 2, 3, name="test", flag=True)
    output=== Forwarding Arguments ===
    Wrapper forwarding:
  2. def wrapper_example(*args, **kwargs): #?wrapper

    15def wrapper_example(*args(1, 2, 3), **kwargs):  #?wrapper16    """Wrapper that forwards everything."""17    print(f"  Wrapper received: args={args(1, 2, 3)}, kwargs={kwargs{'name': 'test', 'flag': True}}")18    print("  Forwarding to inner function...")19    inner_function(*args(1, 2, 3), **kwargs{'name': 'test', 'flag': True})
    output  Wrapper received: args=(1, 2, 3), kwargs={'name': 'test', 'flag': True}
      Forwarding to inner function...
  3. def inner_function(*args, **kwargs):

    5    print("Wrapper forwarding:")6    wrapper_example(1, 2, 3, name="test", flag=True)7    8    print("\n=== Logging Wrapper ===")  #?logging9    logged_add(10, 20)10    logged_multiply(5, 3, verbose=True)11    12    print("\n=== Super() Forwarding ===")  #?super13    fancy = FancyButton("Click Me", color="blue", size="large")1415def wrapper_example(*args, **kwargs):  #?wrapper16    """Wrapper that forwards everything."""17    print(f"  Wrapper received: args={args}, kwargs={kwargs}")18    print("  Forwarding to inner function...")19    inner_function(*args(1, 2, 3), **kwargs{'name': 'test', 'flag': True})2021def inner_function(*args(1, 2, 3), **kwargs):22    print(f"  Inner got: args={args(1, 2, 3)}, kwargs={kwargs{'name': 'test', 'flag': True}}")
    output  Inner got: args=(1, 2, 3), kwargs={'name': 'test', 'flag': True}
    
    === Logging Wrapper ===
  4. result ← 30

    24# Logging wrapper pattern  #?logwrapper25def logged_add(a10, b20):26    print(f"  [LOG] Calling add({a10}, {b20})")27    result→ 30 = a10 + b2028    print(f"  [LOG] Result: {result30}")29    return result30
    output  [LOG] Calling add(10, 20)
      [LOG] Result: 30
  5. logged_add(10, 20)

    8print("\n=== Logging Wrapper ===")  #?logging9logged_add(10, 20)10logged_multiply(5, 3, verbose=True)
  6. def logged_multiply(a, b, verbose=False):

    31def logged_multiply(a5, b3, verboseTrue=FalseFalse):32    if verbose:33        print(f"  [VERBOSE] multiply called with a={a}, b={b}")
  7. if verbose:

    31def logged_multiply(a, b, verbose=False):32    if verboseTrue:33        print(f"  [VERBOSE] multiply called with a={a5}, b={b3}")34    result = a * b
    output  [VERBOSE] multiply called with a=5, b=3
  8. result ← 15

    33    print(f"  [VERBOSE] multiply called with a={a}, b={b}")34result→ 15 = a5 * b335print(f"  [LOG] multiply result: {result15}")36return result15
    output  [LOG] multiply result: 15
  9. logged_multiply(5, 3, verbose=True)

    9logged_add(10, 20)10logged_multiply(5, 3, verbose=True)1112print("\n=== Super() Forwarding ===")  #?super13fancy = FancyButton("Click Me", color="blue", size="large")
    output
    === Super() Forwarding ===
  10. options ← {'color': 'blue', 'size': 'large', 'border': True}

    45class FancyButton(Button):46    def __init__(self⟨FancyButton A⟩, textClick Me, **options):  #?derivedinit47        # Add default options48        options→ {'color': 'blue', 'size': 'large', 'border': True}.setdefault('border', True)49        # Forward to parent
  11. self.text ← Click Me, self.options ← {'color': 'blue', 'size': 'large', 'border': True}

    39class Button:40    def __init__(self⟨FancyButton A⟩, textClick Me, **options):  #?baseinit41        self.text→ Click Me = textClick Me42        self.options→ {'color': 'blue', 'size': 'large', 'border': True} = options{'color': 'blue', 'size': 'large', 'border': True}43        print(f"  Button created: '{textClick Me}' with {options{'color': 'blue', 'size': 'large', 'border': True}}")
    output  Button created: 'Click Me' with {'color': 'blue', 'size': 'large', 'border': True}
  12. fancy ← ⟨FancyButton A⟩

    12    print("\n=== Super() Forwarding ===")  #?super13    fancy→ ⟨FancyButton A⟩ = FancyButton("Click Me", color="blue", size="large")1415def wrapper_example(*args, **kwargs):  #?wrapper16    """Wrapper that forwards everything."""17    print(f"  Wrapper received: args={args}, kwargs={kwargs}")18    print("  Forwarding to inner function...")19    inner_function(*args, **kwargs)2021def inner_function(*args, **kwargs):22    print(f"  Inner got: args={args}, kwargs={kwargs}")2324# Logging wrapper pattern  #?logwrapper25def logged_add(a, b):26    print(f"  [LOG] Calling add({a}, {b})")27    result = a + b28    print(f"  [LOG] Result: {result}")29    return result3031def logged_multiply(a, b, verbose=False):32    if verbose:33        print(f"  [VERBOSE] multiply called with a={a}, b={b}")34    result = a * b35    print(f"  [LOG] multiply result: {result}")36    return result3738# Class inheritance forwarding  #?classforward39class Button:40    def __init__(self, text, **options):  #?baseinit41        self.text = text42        self.options = options43        print(f"  Button created: '{text}' with {options}")4445class FancyButton(Button):46    def __init__(self, text, **options):  #?derivedinit47        # Add default options48        options.setdefault('border', True)49        # Forward to parent50        super().__init__(text, **options)51        print("  (FancyButton enhancements applied)")
    output  (FancyButton enhancements applied)
  13. main()

    53if __name__ == "__main__":54    main()55#@help forward

Wrapper functions use *args, **kwargs to forward all arguments.

Exercise: decorators.py

Use *args/**kwargs in decorator functions