0%

🪄 The Star Opens Endless Paths

Normally a function must know exactly how many arguments to take. But with args you can pass one, two, or hundreds of values collected safely inside a tuple.
🔮 def spell(words): print(words)

Most functions are rigid. They demand a specific number of arguments. No more. No less. But sometimes you want a function that welcomes any number of inputs. One call or one hundred. The same spell works. The * before a parameter name is the key. It gathers all extra positional arguments into a tuple. Inside the function, you can loop through them, count them, or use them as needed.

🕯️ Magic Note

The name args is a convention, not a rule. The star is what matters. You can name it words, items, or *anything. Python collects all unmatched positional arguments into a tuple with that name. If no extra arguments are passed, the tuple is empty.

The syntax def spell(*words): defines a function that accepts any number of arguments. Inside, words is a tuple containing all the values passed. Calling spell(“a”, “b”, “c”) creates the tuple (“a”, “b”, “c”) and prints it.
  • The star parameter must come after all normal parameters
  • It collects only positional arguments, not keyword arguments
  • The tuple can be empty if no arguments are passed
  • Use **kwargs (double star) for keyword arguments
💡 Use *args when you need flexibility in function calls. Great for wrapper functions, decorators, or functions that process a variable number of items. To accept any combination of positional and keyword arguments, use def func(*args, **kwargs). This pattern is common in decorators and function wrappers.
Function CallContent of *words
spell()()
spell(“magic”)(“magic”,)
spell(“a”, “b”, “c”)(“a”, “b”, “c”)
spell(1, 2, 3, 4, 5)(1, 2, 3, 4, 5)
⚠️ The *words parameter collects only arguments that are not matched by preceding parameters. If your function has def func(x, *words), the first argument goes to x and the rest go to words. Also note that *words cannot be followed by a normal parameter without using keyword-only arguments with * as a separator.
Examples

Python

# Basic *args usage

def sum_all(*numbers):

return sum(numbers)

print(sum_all(1, 2, 3, 4))

# Output: 10

print(sum_all(5, 10))

# Output: 15

Python

# Combining normal parameters with *args

def introduce(greeting, *names):

for name in names:

print(f”{greeting}, {name}”)

introduce(“Hello”, “Ali”, “Sara”, “Feloriya”)

# Output: Hello, Ali

# Output: Hello, Sara

# Output: Hello, Feloriya

Python

# Using *args in a decorator

def log_call(func):

def wrapper(*args, **kwargs):

print(f”Called with {args} and {kwargs}”)

return func(*args, **kwargs)

return wrapper

@log_call

def add(x, y):

return x + y

add(3, 5)

# Output: Called with (3, 5) and {}

Common Mistakes
  • Placing *args before normal parameters, causing the normal parameters to never receive values
  • Forgetting that *args collects only positional arguments, not keyword arguments like spell(a=1)
  • Trying to name the star parameter *self inside class methods, which conflicts with instance reference conventions

⚡ Whisper

One star opens infinite doors. The function no longer counts your offerings. It accepts all with silence. One value. Many values. None at all. The star embraces every path.