Python Curiosities: Default Args, GIL, and Indentation

Welcome to the second edition of this weekly series where we look at the surprising sides of programming languages. Today we have a look at some Python features. Whether you write Python daily or just encounter it occasionally, there are a few design decisions in the language that are worth understanding in detail. They affect how your code behaves in ways that are not always obvious. Python allows you to set default values for function parameters. This is a common and useful feature. What surprises many developers is that mutable default values, such as lists or dictionaries, are created once at function definition time, not each time the function is called. If you define a function with an empty list as a default parameter and then append to it inside the function body, that list persists between calls. The second call sees the data from the first. This is not a bug. Python evaluates default arguments when the def statement is executed, and the resulting object is stored as part of the function. The standard workaround is to use None as the default and create a new list inside the function body. It is a small detail, but it is one of the most frequently encountered sources of unexpected behavior in Python. The second curiosity is the Global Interpreter Lock, commonly known as the GIL. CPython, the reference implementation of Python, uses a mechanism that allows only one thread to execute Python bytecode at a time. This means that even on a machine with multiple CPU cores, threads in a Python program do not run Python code in true parallel. The GIL exists to protect the internal memory management of CPython, which uses reference counting for garbage collection. Without the lock, concurrent reference count updates could corrupt memory. For I/O-bound tasks like network requests or file operations, threading still works well because the GIL is released during I/O waits. For CPU-bound work, the common alternatives are the multiprocessing module, which spawns separate processes each with their own GIL, or libraries like NumPy that release the GIL during heavy computation in C. The third curiosity is that Python uses indentation as part of its syntax. In most languages, indentation is a matter of style. In Python, it determines program structure. A block of code is defined by its indentation level, not by braces or keywords. If the indentation is inconsistent, the program does not run. This was a deliberate design choice by Guido van Rossum to enforce readable code at the language level. It removes an entire category of formatting debates but introduces a constraint that many developers coming from C-style languages find unusual at first. Three aspects of Python that are easy to miss in tutorials but relevant in practice. Next Friday, we continue with a different language. #Python #Programming #SoftwareEngineering #FridayLanguageCuriosities #CodeCuriosities #CPython #GIL #DevCommunity

  • No alternative text description for this image

that mutable default trap caught me early on too. had to re-learn how the function scope worked for that.

To view or add a comment, sign in

Explore content categories