PYTHON • FUNCTIONS AND PROGRAM STRUCTURE

Positional vs. Keyword Arguments — Use positional vs keyword arguments

Master the two ways Python lets you pass data into functions for cleaner, more flexible code.

Historical Context & Motivation

When programming languages were first created in the 1950s and 1960s, functions could only receive data in one rigid way: you had to pass values in the exact order the function expected. If a function needed a name and then an age, you could never swap them. This worked for small programs, but as software grew more complex, developers wanted more flexibility. The idea of keyword arguments — where you explicitly name each piece of data you're passing — emerged as a powerful solution. Python, designed by Guido van Rossum, embraced both styles from its earliest versions, giving programmers the freedom to choose whichever approach makes their code clearest.

1957
FORTRAN Introduces Subroutines
FORTRAN, one of the first high-level languages, allows functions (subroutines) with strictly positional parameters. Every argument must appear in the correct order — no exceptions.
1980
Ada Pioneers Named Parameters
The Ada programming language, built for safety-critical systems, introduces named (keyword) arguments so that developers can write self-documenting function calls and avoid dangerous order mistakes.
1991
Python 0.9 Launches with Both Styles
Guido van Rossum releases Python with support for both positional and keyword arguments, plus default values — making functions remarkably flexible from day one.
2020
Python 3.8 Adds Positional-Only Syntax
Python 3.8 introduces the / syntax to mark certain parameters as positional-only, giving library authors fine-grained control over how their functions are called.

So the core question this lesson addresses is: when you call a function, how do you decide whether to pass arguments by position or by keyword name? And what are the trade-offs of each approach? Let's find out.

Core Principles & Definitions

Before we dive into examples, let's define the key terms. A parameter is the variable name listed in a function's definition — it's like a placeholder waiting for a value. An argument is the actual value you pass to the function when you call it. Think of a parameter as a labeled empty box, and an argument as the item you place inside that box.

1

Positional Arguments

Values matched to parameters by their position (order) in the function call. The first argument goes to the first parameter, the second to the second, and so on.
2

Keyword Arguments

Values explicitly paired with a parameter name using the = sign. Order doesn't matter because Python knows exactly where each value belongs.
3

Default Values

Parameters can be given a fallback value in the function definition. If the caller doesn't provide that argument, the default is used automatically.
4

Mixing Styles

You can use positional and keyword arguments in the same call, but all positional arguments must come before any keyword arguments.
✦ KEY TAKEAWAY
Think of ordering food at a restaurant. Positional arguments are like telling the server "I'll have a burger, fries, and a soda" — the server assumes the first item is the main, the second is the side, and the third is the drink based on order. Keyword arguments are like saying "for my drink I'd like soda, for my side I'd like fries, and for my main I'd like a burger" — you can say them in any order because you've labeled each one.

Visual Explanation

The diagram below illustrates how Python matches arguments to parameters in both positional and keyword styles. Notice how positional arguments rely on order, while keyword arguments use explicit naming to find their target parameter.

In the top section, positional arguments are matched left-to-right: the first value goes to name, the second to greeting, and the third to punctuation. In the bottom section, keyword arguments are matched by name, so they can appear in any order.

As you can see, the positional approach is concise — you just list the values. But if someone reads the call greet("Alice", "Hello", "!") without seeing the function definition, it may not be obvious which string is the name and which is the greeting. The keyword approach is a bit longer to type, but it's self-documenting — anyone reading the code can immediately understand what each argument represents.

How Python Resolves Arguments

When Python encounters a function call, it follows a specific algorithm to assign each argument to the correct parameter. Understanding this process helps you avoid common errors like TypeError and SyntaxError. Here is the step-by-step mechanism Python uses internally.

The Argument Resolution Algorithm

  1. Step 1: Python scans all positional arguments in the call from left to right and assigns them to parameters in the same left-to-right order.
  2. Step 2: Python then processes keyword arguments. For each one, it looks up the parameter with the matching name and assigns the value.
  3. Step 3: If any parameter still has no value and has a default defined, Python fills it with that default.
  4. Step 4: If any parameter still has no value and no default, Python raises a TypeError saying the argument is missing.

The Golden Rule

⚠️ SYNTAX RULE
In a function call, all positional arguments must come before keyword arguments. Writing greet(name="Alice", "Hello", "!") causes a SyntaxError because Python sees keyword arguments followed by positional ones.

Default Parameter Values

When you define a function, you can assign default values to parameters. For example, def greet(name, greeting="Hi", punctuation="."): means you only need to provide name — the other two have sensible fallbacks. Parameters with defaults must appear after parameters without defaults in the function definition. This rule ensures Python can always match positional arguments unambiguously.

Common Patterns & Classification

In real-world Python code, you'll encounter several common patterns for how positional and keyword arguments are combined. The diagram below classifies the four main calling patterns you'll use, from simplest to most advanced.

The four main argument-passing patterns, from all-positional to default-heavy. As functions grow more complex, keyword arguments and defaults become increasingly valuable for readability.
Common calling patterns in everyday Python code
PatternExample CallBest For
All positionalprint("hello")Simple, well-known functions
All keyworddict(name="Jo", age=16)Clarity when argument purpose isn't obvious
Mixedsorted(data, reverse=True)Required data + optional config
Defaults onlyopen("file.txt")Functions with many rarely-changed options

Worked Example

Let's walk through a complete example of writing a function and calling it with different argument styles. We'll build a function that calculates a student's weighted grade.

Building a Weighted Grade Calculator
1
Step 1 — Define the function with parameters and defaultsWe create a function called weighted_grade that takes a student's homework score, test score, and optional weights. The weights have default values that add up to 1.0 (100%).
def weighted_grade(homework, test, hw_weight=0.4, test_weight=0.6): return homework * hw_weight + test * test_weight
2
Step 2 — Call with all positional argumentsWe pass all four values by position. The order must exactly match the parameter order: homework, test, hw_weight, test_weight.
weighted_grade(85, 92, 0.3, 0.7) → result is 85 × 0.3 + 92 × 0.7 = 25.5 + 64.4 = 89.9
3
Step 3 — Call with keyword arguments for clarityUsing keyword arguments makes the call much more readable. We can even reorder the weights to put test_weight first — Python will still match correctly because we've named each argument.
weighted_grade(homework=85, test=92, test_weight=0.7, hw_weight=0.3) → same result: 89.9
4
Step 4 — Use defaults by omitting optional argumentsSince hw_weight and test_weight have defaults (0.4 and 0.6), we can skip them entirely. Python uses the defaults automatically.
weighted_grade(85, 92) → 85 × 0.4 + 92 × 0.6 = 34.0 + 55.2 = 89.2
5
Step 5 — Mix positional and keyword for the best of both worldsThe most common real-world pattern: pass the obvious required values positionally, then use keywords for optional settings. This keeps the call short but clear.
weighted_grade(85, 92, test_weight=0.7) → but wait — this causes a problem! hw_weight still defaults to 0.4, and 0.4 + 0.7 = 1.1. The function runs but gives a misleading grade. This shows why you should validate your inputs when designing functions with defaults.

Strengths & Limitations of Each Style

Neither positional nor keyword arguments are universally "better." Each has strengths that shine in different situations. The table below compares them across the dimensions that matter most when writing clean, maintainable Python code.

Positional vs. keyword arguments compared across key dimensions
DimensionPositional ArgumentsKeyword Arguments
ReadabilityGood for 1−2 obvious args; unclear with 3+Excellent — each argument is self-labeled
BrevityShorter to type, less visual clutterLonger, can feel verbose for simple calls
Order flexibilityNone — order must match exactlyFull — any order works
Error riskEasy to swap similar-type args accidentallyTypos in keyword names cause errors (but caught early)
With defaultsMust provide all preceding args to reach later onesCan skip any defaulted parameter by name
✦ KEY TAKEAWAY
Use positional arguments when a function has few parameters whose purpose is obvious from context (like len(my_list)). Switch to keyword arguments whenever the call would be confusing without labels, especially for boolean flags like verbose=True or when a function has three or more parameters.

Connection to Advanced Concepts

Once you're comfortable with basic positional and keyword arguments, Python offers even more powerful tools for handling function parameters. These advanced features build directly on the concepts you've learned in this lesson.

How today's concepts connect to more advanced Python features
This LessonAdvanced FeatureWhat It Does
Positional arguments*argsCollects any number of positional arguments into a tuple
Keyword arguments**kwargsCollects any number of keyword arguments into a dictionary
Parameter order rulesPositional-only ( / ) and keyword-only ( * )Force callers to use only positional or only keyword for specific params
Default valuesMutable default trapUsing lists/dicts as defaults is dangerous — they're shared across calls
🔭 LOOKING AHEAD
In future lessons, you'll learn about *args and **kwargs, which let you write functions that accept a variable number of arguments. These are the foundation for many Python libraries and frameworks. Mastering positional and keyword arguments now will make learning *args and **kwargs feel like a natural next step.

Practice Problems

PROBLEM 1 — CONCEPTUAL
Explain in your own words the difference between a parameter and an argument. Then explain why the following call would produce the same output as greet("Alice", "Hello"): greet(greeting="Hello", name="Alice")
PROBLEM 2 — BASIC
Given the function def power(base, exponent=2): that returns base ** exponent, what does each of the following calls return? (a) power(3) (b) power(3, 4) (c) power(exponent=3, base=2)
PROBLEM 3 — INTERMEDIATE
Consider this function: def describe_pet(name, animal="dog", trick="sit"): which returns f"{name} is a {animal} that can {trick}." Write three different calls that all produce the output: "Whiskers is a cat that can sit." Use (a) all keyword arguments, (b) mixed positional and keyword, and (c) a call that relies on the default for trick.
PROBLEM 4 — APPLIED
You're building a tip calculator function. Write a function called calculate_tip that takes bill_amount (required), tip_percent (default 18), and split (default 1). It should return the total per person (bill + tip divided by split). Then show how to call it for a $60 bill with 20% tip split 3 ways using mixed positional and keyword arguments.
PROBLEM 5 — CRITICAL THINKING
A classmate writes the following function and calls: def register(name, grade=9, sport="track"): ... and then calls register("Maya", sport="soccer"). They expect grade to remain the default (9). Will this work correctly, or will Python raise an error? Explain the argument resolution process step by step. Then propose a scenario where using all positional arguments for this function could lead to a subtle, hard-to-catch bug.

Lesson Summary

Python functions accept data through positional arguments, which are matched by order, and keyword arguments, which are matched by name. Parameters are the placeholders in the function definition, while arguments are the actual values passed during a call. You can mix both styles in a single call, but positional arguments must always come before keyword arguments.

Use positional arguments for simple, obvious calls with few parameters. Switch to keyword arguments when a function has many parameters, uses default values you want to selectively override, or when readability matters more than brevity. This foundation prepares you for advanced features like *args and **kwargs, which extend positional and keyword arguments to accept variable numbers of inputs.

Varsity Tutors • Python • Positional vs. Keyword Arguments