Function Definition with Simple Parameters

by Christoph Schiessl on Python

A few days ago, I introduced you to the basics of Function Definitions in Python. Today, we will build on that and explore functions with simple parameters. We will again use the official grammar, taken from the official Language Reference, as a guide:

funcdef                   ::=  [decorators] "def" funcname [type_params] "(" [parameter_list] ")"
                               ["->" expression] ":" suite
decorators                ::=  decorator+
decorator                 ::=  "@" assignment_expression NEWLINE
parameter_list            ::=  defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
                                 | parameter_list_no_posonly
parameter_list_no_posonly ::=  defparameter ("," defparameter)* ["," [parameter_list_starargs]]
                               | parameter_list_starargs
parameter_list_starargs   ::=  "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
                               | "**" parameter [","]
parameter                 ::=  identifier [":" expression]
defparameter              ::=  parameter ["=" expression]
funcname                  ::=  identifier

For today, we are focusing on the line defining parameter_list_no_posonly, because this is the simplest case to look at.

Python 3.12.1 (main, Jan 12 2024, 21:48:18) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo(a, b,):
...     pass
...

So, here we have defined a new function foo() with two required parameters a and b. Take note of the trailing comma in the parameter list ... the optional trailing comma has no effect whatsoever, but it is valid syntax — some developers like to work with trailing commas. Anyway, both parameters of foo() can be provided as positional or as keyword parameters — this is up to the caller. All of the following are valid:

>>> foo(1, 2)
>>> foo(1, b=2)
>>> foo(a=1, b=2)

However, we cannot arbitrarily mix positional and keyword parameters because all positional parameters must come first. If we try to place keyword parameters first, we get a SyntaxError:

>>> foo(a=1, 2)
  File "<stdin>", line 1
    foo(a=1, 2)
              ^
SyntaxError: positional argument follows keyword argument

As I said before, both parameters are required. Therefore, all of the following calls are incorrect and lead to TypeErrors:

>>> foo(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'b'
>>> foo(a=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'b'
>>> foo(b=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'a'

There's one more edge case I can think of:

>>> foo(1, a=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'a'

In this case, we also get a TypeError, because we have essentially provided two values for the parameter a. The integer 1, through the positional argument, and the integer 2, through the keyword argument. Apart from that, there is also the problem that we didn't provide the required parameter b at all.

That's it for today. Thank you for reading, and please feel free to reach out to me with comments and questions if you have any.

Web App Reverse Checklist

Ready to Build Your Next Web App?

Get my Web App Reverse Checklist first ...


Software Engineering is often driven by fashion, but swimming with the current is rarely the best choice. In addition to knowing what to do, it's equally important to know what not to do. And this is precisely what my free Web App Reverse Checklist will help you with.

Subscribe below to get your free copy of my Reverse Checklist delivered to your inbox. Afterward, you can expect one weekly email on building resilient Web Applications using Python, JavaScript, and PostgreSQL.

By the way, it goes without saying that I'm not sharing your email address with anyone, and you're free to unsubscribe at any time. No spam. No commitments. No questions asked.

Continue Reading?

Here are a few more Articles for you ...


Function Definition Basics

Explore Python's function definition statement and discover its features with this series of articles. Get started with this simple introduction.

By Christoph Schiessl on Python

Function Definition with Keyword-Only Parameters

Learn about keyword-only parameters in Python, how to define them, and their interplay with position-only parameters.

By Christoph Schiessl on Python

Function Definition with Default Parameters

Learn about Python functions with default parameters. Understand how default parameters work and some essential restrictions and evaluation rules.

By Christoph Schiessl on Python

Christoph Schiessl

Hi, I'm Christoph Schiessl.

I help you build robust and fast Web Applications.


I'm available for hire as a freelance web developer, so you can take advantage of my more than a decade of experience working on many projects across several industries. Most of my clients are building web-based SaaS applications in a B2B context and depend on my expertise in various capacities.

More often than not, my involvement includes hands-on development work using technologies like Python, JavaScript, and PostgreSQL. Furthermore, if you already have an established team, I can support you as a technical product manager with a passion for simplifying complex processes. Lastly, I'm an avid writer and educator who takes pride in breaking technical concepts down into the simplest possible terms.