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.

Code braces with terminal and markup symbols representing Python programming.
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

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.

SECTION 2

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.

SECTION 3

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.

How Python Matches Arguments to ParametersPOSITIONAL ARGUMENTSdef greet(name, greeting, punctuation): print(greeting + ", " + name + punctuation)greet("Alice", "Hello", "!")"Alice""Hello""!"→ name→ greeting→ punctuationKEYWORD ARGUMENTSdef greet(name, greeting, punctuation): print(greeting + ", " + name + punctuation)greet(punctuation="!", name="Alice", greeting="Hello")punctuation="!"name="Alice"greeting="Hello"Keyword args can appear in any order — Python matches by name, not position.
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.

SECTION 4

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.

SECTION 5

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.

Four Calling PatternsPATTERN 1: ALL POSITIONALdef area(length, width): return length * widtharea(10, 5) # → 50PATTERN 2: ALL KEYWORDdef area(length, width): return length * widtharea(width=5, length=10) # → 50PATTERN 3: MIXEDdef send(to, subject, urgent=False): ...send("bob@mail.com", "Hi", urgent=True)PATTERN 4: WITH DEFAULTSdef connect(host, port=80, secure=False): ...connect("example.com") # uses # port=80, secure=FalseWhen to Use Each PatternAll Positional — Best for 1−2 obvious args (e.g., math operations)All Keyword — Best when argument meaning isn't obvious from contextMixed — Best when some args are required and others are optional flagsWith Defaults — Best for functions with many configurable options
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.
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

Common calling patterns in everyday Python code

SECTION 6

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. 1

    Step 1 — Define the function with parameters and defaults

    We 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. 2

    Step 2 — Call with all positional arguments

    We 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. 3

    Step 3 — Call with keyword arguments for clarity

    Using 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. 4

    Step 4 — Use defaults by omitting optional arguments

    Since 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. 5

    Step 5 — Mix positional and keyword for the best of both worlds

    The 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.

SECTION 7

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.

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

Positional vs. keyword arguments compared across key dimensions

✦

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.

SECTION 8

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.

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

How today's concepts connect to more advanced Python features

ℹ

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.

SECTION 9

Practice Problems

Question 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")
Show answer
A parameter is the variable name defined in the function header (like name and greeting in def greet(name, greeting)). An argument is the actual value you pass in when calling the function (like "Alice" and "Hello"). The two calls produce the same output because keyword arguments match by name, not by position. Even though "Hello" comes second positionally and first in the keyword version, both calls assign "Alice" to name and "Hello" to greeting.

Question 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)
Show answer
(a) power(3) returns 9. Since exponent defaults to 2, this computes 3² = 9. (b) power(3, 4) returns 81. Both values are positional: base=3, exponent=4, so it computes 3⁴ = 81. (c) power(exponent=3, base=2) returns 8. Using keyword arguments, base=2 and exponent=3, computing 2³ = 8. The reversed order doesn't matter because each argument is explicitly named.

Question 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.
Show answer
(a) All keyword: describe_pet(name="Whiskers", animal="cat", trick="sit") — every argument is named explicitly. (b) Mixed: describe_pet("Whiskers", animal="cat", trick="sit") — "Whiskers" is positional (first = name), and the rest are keyword. (c) Using default: describe_pet("Whiskers", animal="cat") — since trick defaults to "sit", we can omit it entirely. All three calls produce the same string because Python matches every argument to the correct parameter regardless of method.

Question 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.
Show answer
The function definition: def calculate_tip(bill_amount, tip_percent=18, split=1): return (bill_amount + bill_amount * tip_percent / 100) / split. A clean mixed call: calculate_tip(60, tip_percent=20, split=3). This passes 60 positionally to bill_amount, then uses keywords for clarity on the other two. The result is (60 + 60 × 20 / 100) / 3 = (60 + 12) / 3 = 72 / 3 = 24.0 per person. The keyword style makes the call easy to read without checking the function definition.

Question 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.
Show answer
This call works correctly. Python first assigns the positional argument "Maya" to the first parameter (name). Then it processes the keyword argument sport="soccer", assigning "soccer" to the sport parameter. Finally, grade has no value yet but has a default of 9, so Python uses that default. No error occurs. A subtle bug scenario: if a caller writes register("Maya", "soccer") intending "soccer" to be the sport, Python would actually assign "soccer" to grade (the second positional parameter), not to sport. The function wouldn't crash — it would silently set grade to the string "soccer" and use the default "track" for sport. This is a real-world example of why keyword arguments prevent position-order bugs, especially when parameters have similar data types.

SUMMARY

Lesson Summary

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