sodcalculator

10 Tech How-To

Python Default & Positional-Only Arguments Guide

Guide 10-21603 · Updated · Step by step

This guide shows you how to combine default keyword arguments with positional-only parameters in Python, a technique that gives you both flexible function calls and strict control over how arguments are passed. You’ll learn the syntax, practical use cases, and common pitfalls, so you can write cleaner, more intentional APIs.

What You’ll Need

  • Python 3.8 or later (positional-only parameters were introduced in Python 3.8)
  • A text editor or IDE of your choice
  • Basic familiarity with defining functions and using keyword arguments

Step-by-Step

  1. Understand the two concepts separately. A default argument has a value assigned in the function definition, like def greet(name, greeting="Hello"). A positional-only parameter must be passed by position, not by keyword. You mark it with a / in the parameter list.
  2. Place the slash correctly. The / goes after the last positional-only parameter. Everything before it is positional-only; everything after can be positional or keyword (unless you also add a *). Example: def func(a, b, /, c, d): — here a and b are positional-only, while c and d can be passed either way.
  3. Add default values to positional-only parameters. You can give defaults to parameters before the slash. For example: def connect(host, port=8080, /, timeout=5):. Here host and port must be passed by position, but port can be omitted. timeout can be passed by keyword.
  4. Call the function correctly. For the above, valid calls are connect("localhost"), connect("localhost", 9090), and connect("localhost", 9090, timeout=10). Invalid: connect(host="localhost") — it will raise a TypeError because host is positional-only.
  5. Combine with keyword-only arguments (the * marker). You can have both positional-only and keyword-only in the same function. Syntax: def func(a, /, b, *, c). Here a is positional-only, b can be either, and c must be passed by keyword. This gives you the full spectrum of argument passing styles.
  6. Use defaults in each section. You can assign defaults to parameters in any section: before /, between / and *, and after *. For instance: def config(debug=False, /, level=1, *, save=True). All three have defaults, but debug must be passed positionally, level can be either, and save must be keyword.
  7. Test with a simple example. Write a function that formats a message: def format_msg(text, upper=False, /, prefix=""):. Call it as format_msg("hello", True) and format_msg("hi", prefix="Note: "). Notice you cannot use text= or upper= in the call.
  8. Check the signature with help() or inspect. Use help(your_function) in the REPL to see the signature. It will show (text, upper=False, /, prefix=''), making it clear which are positional-only.
  9. Refactor an existing function. If you have a function where you want to prevent keyword usage for certain parameters (e.g., to avoid breaking future changes), add a / after those parameters. Test that existing calls still work if they were positional.
  10. Document your intent. Add a docstring that explicitly states which parameters are positional-only and why. This helps other developers (and future you) understand the design choice.

Common Mistakes

  • Placing the slash in the wrong spot. The / must come after the last positional-only parameter. Putting it before or in the middle of parameters changes their meaning.
  • Forgetting that defaults don’t make a parameter keyword-able. A parameter with a default before the / is still positional-only. You can omit it, but you cannot use its name in the call.
  • Confusing / with *. / marks positional-only, * marks keyword-only. They are not interchangeable.
  • Using keyword arguments for positional-only parameters. This raises TypeError: got some positional-only arguments passed as keyword arguments. It’s a common error when refactoring.
  • Assuming all parameters after / are keyword-only. They are not; they can still be passed positionally unless you add a *.

Tips

  • Use positional-only when parameter names are not meaningful. For example, in a math function like def power(base, exp, /), the names are internal; forcing positional calls makes the API cleaner.
  • Use positional-only to allow future renaming. If you might rename a parameter later, making it positional-only means you won’t break existing keyword calls.
  • Combine with keyword-only for maximum clarity. For functions with many parameters, use positional-only for the core inputs and keyword-only for options.
  • Keep defaults at the end of each section. Python requires that parameters without defaults come before those with defaults within the same section. For example, def f(a, /, b=1, c=2) is fine, but def f(a=1, /, b) is a syntax error.
  • Use / in library code. If you’re writing a public API, positional-only parameters prevent users from relying on parameter names, giving you freedom to change them later.

Troubleshooting

Symptom: You get a SyntaxError when defining the function.
Cause: You’re using Python 3.7 or earlier, or the slash is in the wrong place.
Fix: Upgrade to Python 3.8+. Check the placement: / must be after the last positional-only parameter. Also ensure there’s no comma after the slash (e.g., def f(a, /,) is invalid).

Symptom: TypeError: f() got some positional-only arguments passed as keyword arguments.
Cause: You’re trying to pass a positional-only parameter by name.
Fix: Change the call to pass that argument positionally. For example, if def f(a, /), call f(5) not f(a=5).

Symptom: The function works but you’re not sure which parameters are positional-only.
Cause: The signature is not obvious from the code.
Fix: Use inspect.signature(your_func) in the REPL. It will print the signature with the / marker. Also read the docstring if available.

Symptom: You get a TypeError: multiple values for argument when calling.
Cause: You’re passing a value both positionally and by keyword for a parameter that is not positional-only.
Fix: Remove the duplicate. For example, def f(a, b): — calling f(1, b=2) is fine, but f(1, a=2) raises this error.

Frequently Asked Questions

Can I have a default value on a positional-only parameter?

Yes. You can assign a default just like any other parameter. The default is used when you omit that argument in the call, but you still cannot pass it by keyword.

What is the difference between / and *?

/ marks parameters before it as positional-only (must be passed by position). * marks parameters after it as keyword-only (must be passed by keyword). They can be used together.

Can I use / in lambda functions?

No. Lambda functions do not support the slash or star syntax. They are limited to simple parameter lists.

Does using / affect performance?

No. It’s purely a syntax feature; there is no runtime performance difference. It only affects how the function can be called.

Is / supported in Python 3.7?

No. It was introduced in Python 3.8. If you need to support older versions, you cannot use positional-only parameters.

Can I have a parameter that is both positional-only and keyword-only?

No, that’s contradictory. A parameter is either positional-only, keyword-only, or both (the default). You cannot have both restrictions at once.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →