Originally published on CodingCush.
Python function arguments are the values you pass into a function when you call it, so the function can work with real data instead of fixed values. You can pass them by position, by name, or not at all if the function has a default value. Python also lets a function accept any number of extra values, using *args for positional values and **kwargs for named values. Learn these five styles and you can read most function definitions calmly and write flexible functions of your own.
Parameters and Arguments: What Is the Difference?
A parameter is the variable name inside the brackets when you define a function. An argument is the actual value you send when you call it. Think of a parameter as an empty labelled box, and an argument as the thing you place inside it.
def greet(name): # name is a parameter
print("Hello, " + name)
greet("Asha") # "Asha" is an argument
The function is defined once, but works for many names because each call brings its own argument. If functions are still new to you, start with our guide to Python functions explained with examples, then return here. When Python says "missing 1 required positional argument", it means a value was not passed at call time.
Positional Arguments: Order Matters
A positional argument is matched to a parameter by its position. The first value goes to the first parameter, the second to the second, and so on. It works like a queue at a ticket counter. Everyone is served in order, and swapping places changes who gets which ticket.
def describe_pet(animal, name):
print(name + " is a " + animal)
describe_pet("dog", "Bruno") # Bruno is a dog
describe_pet("Bruno", "dog") # dog is a Bruno (oops)
The second call raises no error, because both values are strings. Python follows the order you gave, even when the result is nonsense. Positional arguments are clean for short functions with obvious inputs. For longer lists, keyword arguments are safer.
Keyword Arguments: Pass Values by Name
A keyword argument names the parameter it belongs to, using name=value inside the call. Because each value is labelled, the order does not matter, and readers can understand your call without opening the function definition.
describe_pet(name="Bruno", animal="dog")
describe_pet(animal="cat", name="Milo")
Both calls work correctly, despite the different order. Keyword arguments shine when a function has several parameters, or when a bare value like 30 would be hard to guess. Writing timeout=30 is far clearer. You can mix both styles, but positional arguments must come before keyword arguments.
Positional vs Keyword Arguments at a Glance
| Feature | Positional Arguments | Keyword Arguments |
|---|---|---|
| How matched | By position, in order | By parameter name |
| Order matters? | Yes, strictly | No, any order works |
| Readability | Good for short calls | Clearer for long calls |
| Typical use | Required, obvious values | Options and settings |
| Main risk | Swapped values, silent bugs | A wrong name raises an error |
Most real code uses both: positional arguments for the main data, keyword arguments for options.
Default Arguments: Values That Fill Themselves In
A default argument gives a parameter a ready value in the definition. If the caller passes nothing, Python uses the default. If the caller passes a value, that value wins. Defaults suit settings that rarely change, such as a greeting or page size.
def greet(name, greeting="Hello"):
print(greeting + ", " + name)
greet("Asha") # Hello, Asha
greet("Asha", "Good morning") # Good morning, Asha
One firm rule: parameters with defaults must come after parameters without defaults, or Python raises a SyntaxError. Defaults also make functions easy to extend, since old calls keep working when you add a new optional parameter later.
The More on Defining Functions section of the Python Tutorial on docs.python.org.
The Mutable Default Trap, and the None Fix
Here is a famous trap. A default value is created only once, when the function is defined, not fresh on every call. That is harmless for numbers and strings, but risky for mutable defaults like a list, because every call shares the same object.
def add_item(item, basket=[]): # risky default
basket.append(item)
return basket
print(add_item("apple")) # ['apple']
print(add_item("banana")) # ['apple', 'banana'] - surprise!
The second call remembered the first, like a basket that never gets emptied. The safe pattern is to use None as the default, then create a fresh list inside the function.
def add_item(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
Now every call starts with a new empty list. Quick rule: numbers, strings, tuples and None are safe defaults. Mutable defaults deserve a second look.
*args: Accept Any Number of Positional Values
Sometimes you do not know how many values a function will receive. A total function might get two numbers today and twenty tomorrow. That is what *args is for. The star collects extra positional arguments into a tuple, which your function can loop over.
def total(*args):
result = 0
for number in args:
result += number
return result
print(total(2, 3)) # 5
print(total(10, 20, 30, 5)) # 65
The name args is a convention, not a keyword. Python cares about the star, but other programmers expect args, so use it. Inside the function, args supports len(), indexing and loops. Use *args when all values are the same kind of thing, like numbers to add.
**kwargs: Accept Any Number of Keyword Values
The partner of *args is **kwargs, which collects extra keyword arguments into a dictionary. The caller can pass any named options, even ones you did not list as parameters, and your function reads them by key.
def build_profile(**kwargs):
for key, value in kwargs.items():
print(key + ": " + str(value))
build_profile(name="Asha", city="Pune", course="Python")
This suits settings and profiles, where options vary per call. Because kwargs is a normal dictionary, kwargs.get("city", "Unknown") reads a value safely with a fallback. Flexible arguments appear inside classes often too, so our guide to Python classes and objects explained is a good next step.
Mixing Arguments: The Order Rules
One function can combine regular parameters, defaults, *args and **kwargs, but Python enforces a fixed order in the definition: regular parameters, then defaults, then *args, then keyword-only parameters, and finally **kwargs. In a call, positional values come first, then keyword values.
def order_summary(item, quantity=1, *extras, **options):
print(item, quantity, extras, options)
order_summary("Notebook", 2, "pen", "ruler", gift_wrap=True)
Here Notebook fills item, 2 fills quantity, the extra words land in extras, and gift_wrap lands in options. A positional value after a keyword one raises a SyntaxError. The official tutorial covers these rules in depth in More on Defining Functions in the Python Tutorial, worth a slow read after this article.
Unpacking with * and ** When Calling
The stars also work in the other direction. When calling, one star unpacks a list or tuple into positional arguments, and two stars unpack a dictionary into keyword arguments. This is very useful when your data already sits in a list or dictionary.
pet_list = ["dog", "Bruno"]
describe_pet(*pet_list) # same as describe_pet("dog", "Bruno")
pet_dict = {"animal": "cat", "name": "Milo"}
describe_pet(**pet_dict) # keys must match parameter names
For dictionary unpacking, every key must match a parameter name exactly, or Python raises a TypeError. If a term feels fuzzy, the Python glossary on docs.python.org gives the official meaning of words like argument and parameter.
Common Mistakes to Avoid
Most argument errors are small and predictable. The regular offenders are passing values in the wrong order, placing a positional value after a keyword one, using a list as a default, misspelling a keyword name, and passing extra values without *args. Read error messages slowly, because Python usually names the exact parameter and problem. When in doubt, use keyword arguments, which fail loudly instead of quietly.
Frequently Asked Questions
Can a function have both *args and **kwargs?
Yes. Use both together, with *args before **kwargs. Positional extras go into the tuple, named extras into the dictionary.
What happens if I pass too many arguments?
Python raises a TypeError. Adding *args and **kwargs is the usual way to accept extras on purpose.
Are default values evaluated on every call?
No. A default is created once, when the function is defined. That is why mutable defaults are shared, and why None is the safe default for lists.
Can I force callers to use keyword arguments?
Yes. Parameters after a bare * are keyword-only, so callers must name them.
Is args a special keyword in Python?
No. The star is the special part. args and kwargs are just names used by convention.
Conclusion
Python function arguments follow a small set of friendly rules. Positional arguments match by order, keyword arguments by name, defaults fill in missing values, *args collects extra positional values into a tuple, and **kwargs collects extra named values into a dictionary. Keep defaults immutable, respect the mixing order, and unpack with the stars when calling. Practise each style in tiny functions, and errors will soon feel like helpful directions.

Top comments (0)