Python Notes
Complete guide to Python function arguments — positional, keyword, default, *args, **kwargs and their real-world use cases. Understand argument types with best practices.
A function needs data to work — this data is called Arguments and Parameters. Python has 5 types of arguments!
1️⃣ Positional Arguments (In sequence order)
| ✍️ Author | Eric Matthes |
| 📅 Year | 2019 |
| 💰 Price | ₹799 |
| ✍️ Author | Luciano Ramalho |
| 📅 Year | 2022 |
| 💰 Price | ₹1299 |
2️⃣ Keyword Arguments (Passing by name)
| 🍕 Order | 2x Large Pizza |
| 🍕 Order | 3x Medium Burger |
| 🍕 Order | 1x Small Pasta |
| 📧 To | rahul@example.com |
| Subject | Python Class Tomorrow |
| Body | Kal subah 10 baje class hogi. Sab log attend ka... |
| CC | priya@example.com |
3️⃣ Default Arguments (Default Values)
| 👤 Name | Deepak |
| Age | 25 |
| Country | India |
| Language | Hindi |
| 👤 Name | Alex |
| Age | 30 |
| Country | USA |
| Language | English |
| 👤 Name | Fatima |
| Age | 28 |
| Country | UAE |
| Language | Hindi |
⚠️ Default Arguments ka Order (Important!)
⚠️ Mutable Default Arguments — Common Pitfall!
4️⃣ *args — Variable Positional Arguments
| Numbers received | (1, 2) |
| Type | <class 'tuple'> |
| Numbers received | (1, 2, 3, 4, 5) |
| Type | <class 'tuple'> |
| Numbers received | (10, 20, 30) |
| Type | <class 'tuple'> |
| 🏢 Team | Team Alpha |
| 👑 Leader | Rajesh |
| 📊 Total | 5 people |
5️⃣ **kwargs — Variable Keyword Arguments
| Type | <class 'dict'> |
| Data | {'name': 'Kavya', 'age': 24, 'city': 'Hyderabad', 'hobby': 'Coding'} |
| Name | Kavya |
| Age | 24 |
| City | Hyderabad |
| Hobby | Coding |
🔀 Combining All Argument Types
| 🛒 Order for | Meera |
| 💸 Subtotal | ₹300 |
| 🏷️ Discount | 10% (saves ₹30) |
| ✅ Total | ₹270 |
| delivery | Express |
| note | Handle with care |
📦 Argument Unpacking (Spread Operator)
🔒 Keyword-Only Arguments (Python 3+)
| User | Arjun, Age: 25, Role: user, Active: True |
| User | Arjun, Age: 25, Role: admin, Active: True |
| User | Arjun, Age: 25, Role: moderator, Active: False |
🔢 Type Hints with Arguments (Python 3.5+)
📊 Arguments Summary Diagram
| Type | Example |
|---|---|
| Positional | func(1, 2, 3) |
| Order MUST match parameters | |
| Keyword | func(a=1, b=2) |
| Order doesn't matter | |
| Default | def func(a, b=10) |
| Optional — has a fallback value | |
| *args | def func(*args) → tuple |
| Unlimited positional args | |
| **kwargs | def func(**kwargs) → dict |
| Unlimited keyword args |
❓ Interview Questions
Q1: What is the difference between *args and **kwargs?
-*args— takes variable positional arguments, stores in a tuple -kwargs— takes variable keyword arguments, stores in a dictionary**
Q2: Can we use only *args or only **kwargs?
def only_args(*args): # ✅ Sirf *args
print(args)
def only_kwargs(**kwargs): # ✅ Sirf **kwargs
print(kwargs)
def both(*args, **kwargs): # ✅ Dono saath
print(args, kwargs)Q3: What is the mutable default argument bug and how to fix it?
# Bug
def bad(lst=[]):
lst.append(1)
return lst
# Fix
def good(lst=None):
if lst is None:
lst = []
lst.append(1)
return lstQ4: How to force keyword-only arguments?
# Parameters after * can only be passed by keyword
def func(a, b, *, c, d=10):
print(a, b, c, d)
func(1, 2, c=3) # ✅
# func(1, 2, 3) # ❌ TypeErrorQ5: How to check a function signature?
import inspect
def my_func(a, b, c=10, *args, **kwargs):
pass
sig = inspect.signature(my_func)
print(sig) # (a, b, c=10, *args, **kwargs)
for name, param in sig.parameters.items():
print(f"{name}: {param.kind.name}")📋 Quick Reference
🚀 Next: For an in-depth guide on Return Statement, see return-statement.mdx!⚠️ Common Mistakes
❌ Mistake 1: Giving Positional after Keyword, then back to Positional
def greet(name, age, city):
print(f"{name}, {age}, {city}")
# ❌ WRONG — positional argument cannot come after keyword
# greet("Rahul", age=25, "Delhi") # SyntaxError!
# ✅ CORRECT — positional first, keyword after
greet("Rahul", age=25, city="Delhi")💡 Rule: Once you start giving keyword arguments, only keyword arguments can follow. You cannot go back to positional!
❌ Mistake 2: Mutable Default Argument use karna (List/Dict)
💡 Remember: Never put List, Dict, Set directly as a default argument. Always use None and create inside.❌ Mistake 3: Treating *args like a Keyword argument
def show(*args):
print(args)
# ❌ WRONG — *args only takes positional values
# show(name="Rahul") # TypeError: got an unexpected keyword argument 'name'
# ✅ SAHI
show("Rahul", 25, "Delhi")💡 Understand the difference:*args= positional values (tuple),**kwargs= keyword values (dict). Don't mix them!
❌ Mistake 4: Placing Default argument before Non-default
# ❌ GALAT — SyntaxError aayega
# def register(country="India", name, age):
# pass
# SyntaxError: non-default argument follows default argument
# ✅ CORRECT — defaults always come after
def register(name, age, country="India"):
print(f"{name}, {age}, {country}")
register("Amit", 22)❌ Mistake 5: Giving the same argument both ways (Positional + Keyword)
def info(name, age):
print(f"{name} is {age}")
# ❌ WRONG — 'name' given twice
# info("Rahul", name="Rahul")
# TypeError: info() got multiple values for argument 'name'
# ✅ CORRECT — give only once
info("Rahul", age=25)❌ Mistake 6: **kwargs mein invalid identifier dena
def show_info(**kwargs):
for k, v in kwargs.items():
print(f"{k}: {v}")
# ❌ WRONG — spaces or special chars cannot directly appear in key names
# show_info(first name="Rahul") # SyntaxError
# ✅ CORRECT — use only valid Python identifiers
show_info(first_name="Rahul", last_name="Sharma")❌ Mistake 7: Putting *args and **kwargs in wrong order
# ❌ WRONG — **kwargs first, *args after is not allowed
# def func(**kwargs, *args): # SyntaxError!
# pass
# ✅ SAHI ORDER: positional → *args → keyword-only → **kwargs
def func(a, b, *args, key="default", **kwargs):
print(f"a={a}, b={b}, args={args}, key={key}, kwargs={kwargs}")
func(1, 2, 3, 4, key="custom", extra="hello")✅ Key Takeaways
- 📌 Parameter is in the function definition, Argument is given in the function call — both are different concepts!
- 1️⃣ Positional Arguments — order matters — wrong order = wrong output. Like writing a phone number in the name field of a form!
- 2️⃣ Keyword Arguments — values are passed by name — order can be anything. This makes code readable and safe.
- 3️⃣ Default Arguments provide optional values — if the user doesn't provide one, a fallback value is used. But beware of mutable defaults (list/dict)!
- 4️⃣ **
*argspacks unlimited positional arguments into a tuple** — when you don't know how many values will come.
- 5️⃣
kwargs packs unlimited keyword arguments into a dictionary** — when you don't know how many named values will come.
- 🔐 Keyword-only arguments — use
*separator to force them — this prevents users from accidentally passing them positionally.
- 📦 Argument Unpacking:
*listunpacks into positional arguments,**dictunpacks into keyword arguments — you can directly call functions from existing data.
- 📏 Order Rule:
positional → *args → keyword-only → **kwargs— yeh sequence kabhi break mat karo!
- 🎯 Type Hints — use them with arguments — code becomes readable and you get autocomplete in the IDE. Must-have for production code!
❓ FAQ
Q1: Is it necessary to name *args exactly "args"?
No! In *args, args is just a convention. You can give any name — what matters is the * (asterisk) operator. Example: *numbers, *items — all valid.
Q2: Can *args and **kwargs be used together?
Yes, absolutely! Both can be used together. Remember the order: *args first, **kwargs after.
def flexible(*args, **kwargs):
print(f"Positional: {args}")
print(f"Keyword: {kwargs}")
flexible(1, 2, 3, name="Rahul", age=25)Q3: Can a function call be given as a default argument? Like def f(x=len([1,2]))?
Yes, you can — but note that this value is evaluated at function definition time, not on every call! If you need dynamic evaluation, use None as default and calculate inside the function.
Q4: Positional-only arguments kya hain? (Python 3.8+)
Python 3.8 introduced the / separator — arguments before it can only be passed positionally:
def divide(a, b, /):
return a / b
print(divide(10, 2)) # ✅ Positional se — works!
# print(divide(a=10, b=2)) # ❌ Keyword se — TypeError!Q5: Why is *args a tuple and not a list?
Tuple is immutable — meaning it cannot be accidentally modified inside the function. This is a safety measure. If you need to modify, convert to list: args = list(args).
Q6: Do unlimited arguments in a function create performance issues?
Normally no. Python tuples and dicts are very optimized. But if you're passing hundreds of thousands of arguments (which is a rare case), memory usage can increase. In normal use (10-100 args), there's no performance issue.
Q7: Is key order maintained in kwargs?
Yes! In Python 3.7+, dictionaries maintain insertion order. So in **kwargs, arguments are received in the same order they were given.
Q8: Can we directly index *args?
Yes! *args is a tuple, so indexing works:
🎯 Interview Questions
Q1: What is the fundamental difference between *args and **kwargs?
Answer:*argscollects variable-length positional arguments into a tuple, whilekwargscollects variable-length keyword arguments into a dictionary**. In*args, values come without names; in**kwargs, each value has a key (name).
Q2: What is the mutable default argument trap? How to avoid it in production code?
Answer: When you use a mutable object (list, dict, set) as a default value, that object is created once at function definition time and is shared across all calls. Fix: UseNoneas default and doif param is None: param = []in the function body. This is Python's most common gotcha.
Q3: What is the real-world use case of Keyword-only and Positional-only parameters?
Answer: Keyword-only (after*): When you want users to explicitly name them — prevents accidental wrong ordering (e.g.,sorted(data, *, key=func, reverse=True)). Positional-only (before/): When the parameter name is an implementation detail and may change in the future (e.g.,len(obj, /)— Python built-ins use this).
Q4: How does argument unpacking (* and **) work in a function call?
Answer:*iterableunpacks a list/tuple into individual positional arguments.**dictunpacks a dictionary into individual keyword arguments. Example:func(*[1,2,3])is the same asfunc(1,2,3). This is powerful for dynamic function calling — when arguments are decided at runtime.
Q5: How to achieve function overloading in Python through arguments?
Answer: Python doesn't have traditional function overloading (like Java/C++). Alternatives: (1) Default arguments for optional params, (2)*args/**kwargsfor flexible signatures, (3)functools.singledispatchdecorator, (4) Type checking inside function. The most Pythonic way is default args +*args/**kwargs.
Q6: What is the use of inspect.signature() in real projects?
Answer: inspect.signature() provides complete parameter info for a function — names, types, defaults, kinds (POSITIONAL_ONLY, KEYWORD_ONLY, etc.). Real uses: (1) Auto-generation of documentation, (2) Writing decorators that preserve the original signature, (3) API frameworks like FastAPI/Flask that map URL parameters to function params, (4) Testing/validation tools.Q7: If a parameter comes after *args, what does it become?
Answer: Any parameter that comes after*argsautomatically becomes a keyword-only argument. Users must provide that value by name only, they cannot pass it positionally. Example:def func(*args, separator="-")— hereseparatorcan only be given asfunc(1, 2, separator="/").
Q8: Python mein pass-by-value hai ya pass-by-reference?
Answer: Python uses pass-by-object-reference (or "pass-by-assignment"). Meaning: the function receives a reference to the object. For immutable objects (int, str, tuple), it appears like pass-by-value (since they can't be modified). For mutable objects (list, dict), it appears like pass-by-reference (since they can be modified in-place). Technically, variable reassignment doesn't affect the original, but mutation does.
Q9: How to forward **kwargs to another function?
Answer: Simply unpack and pass with kwargs. This is very common in decorator patterns and wrapper functions**:def wrapper(*args, **kwargs):
print("Before call")
result = actual_function(*args, **kwargs)
print("After call")
return resultThis pattern is extensively used in decorators, middleware, and proxy functions.
Q10: What is the maximum number of arguments a function can have?
Answer: In Python 3.7+, there was technically a limit of 255 positional arguments in theCALL_FUNCTIONbytecode instruction, but in Python 3.8+ this limit has been effectively removed. With*argsand**kwargs, you can practically pass unlimited arguments — memory is the only limit. But in clean code, if you have more than 5-7 parameters, you should usually use a class/dataclass.
🚀 Next: For an in-depth guide on Return Statement, see return-statement.mdx!Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Function Arguments in Python.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Python Master Course topic.
Search Terms
python-master-course, python master course, python, master, course, functions, function, arguments
Related Python Master Course Topics