DEV Community

Md Mahiuddin
Md Mahiuddin

Posted on

What’s New In Python 3.12

In this concise overview, we'll delve into Python 3.12 and its exciting new features. Additionally, I'll provide my personal insights on each enhancement or adjustment.

  1. Nested F-Strings Python 3.12 introduces a captivating feature: nested f-string expressions. Let's explore a fresh example to illustrate this.
def create_welcome_message(name: str) -> str:
    return f"Welcome, {f"{name}"}!"

visitor_name = "Jennifer"
welcome_message = create_welcome_message(visitor_name)
# Output: Welcome, Jennifer!
Enter fullscreen mode Exit fullscreen mode
  1. Quote Reuse: In Python 3.11, attempting to reuse the same quotation marks within an f-string would result in a SyntaxError. This constraint compelled users to resort to different quotation marks (for instance, using double quotes or triple quotes) if the f-string itself utilized single quotes. However, Python 3.12 introduces a new capability that facilitates more flexible usage:

In Python 3.12 and subsequent versions, you are now able to reuse the same quotation marks that enclose the surrounding f-string without encountering a SyntaxError. This advancement allows for constructs like the following:


words = ['Python', '3.11']
print(f"This is {': '.join(words)}")
# Output: This is Python: 3.11
Enter fullscreen mode Exit fullscreen mode


words = ['Python', '3.12']
print(f"This is: {": ".join(words)}")
# Output: This is Python: 3.12
Enter fullscreen mode Exit fullscreen mode

It's worth noting that there was previously no explicit limitation on the depth of f-string nesting. However, the inability to reuse string quotes within the expression component of f-strings limited the extent to which f-strings could be nested. Even the most complex f-string nesting prior to this change was constrained as follows:


# Output: '2'
Enter fullscreen mode Exit fullscreen mode


# Output: '2'
Enter fullscreen mode Exit fullscreen mode

3. Multiline F-Strings
A remarkable addition in version 3.12 is the ability to create multiline f-strings. In Python 3.11, expressions within f-strings were required to be defined on a single line, even though outside of f-strings, expressions could span multiple lines (such as defining literal lists over multiple lines). This limitation made the f-strings less readable. However, Python 3.12 introduces the ability to define multi-line expressions within f-strings and include comments as well:

greeting = f"Hey there {
    name  #
# Output: Hey there Python
Enter fullscreen mode Exit fullscreen mode

4. Tokenization
Since Python 3.11, the tokenizer module has been built in Python for examining lexical elements and keywords. Now, with the advent of nested and multiline f-strings in 3.12, this module has been reimplemented in C, resulting in nearly a 40% performance boost. This advancement significantly benefits linting and formatting tools that rely on this module.

5. Per-Interpreter GIL
Python 3.12 introduces a groundbreaking feature: the Per-Interpreter GIL. This advancement allows us to exert full control over the Global Interpreter Lock's utilization in sub-interpreters. As the official documentation explains, this feature enables Python programs to optimally utilize multiple CPU cores.

6. Distutils Deprecated
The ongoing debate between setuptools and distutils within the Python community has culminated in the decision to phase out the distutils standard library. Setuptools, a feature-rich fork of distutils, has gained widespread preference. Consequently, distutils has been deprecated.

Moreover, pip employs setuptools to create distributions. If you create a virtual environment with Python versions up to 3.11 and pip versions up to 22.1, you'll notice setuptools is pre-installed.

$ pip list
Package    Version
---------- -------
pip        23.2.1
setuptools 68.0.0    <--
wheel      0.41.1
Enter fullscreen mode Exit fullscreen mode

Given setuptools' independence from distutils and pip's reduced reliance on setuptools for versions 22.1 and beyond, freshly installed Python environments no longer include a distribution tool. The setuptools package no longer depends on the virtualenv package either. Thus, even with setuptools installed, you cannot create a virtual environment using commands like:

$ python -m venv venv
# ERROR: venv module is not found.
Enter fullscreen mode Exit fullscreen mode

The distutils package has become an external third-party package. To access both virtualenv and setuptools functionalities, separate installations are required.

7. kwargs Type Hinting
Python 3.12 introduces significant changes to the typing module. Previously, I used typing.Any for type hinting **kwargs in functions and methods. With Python 3.12, type annotations can be more precise using typing.TypedDict.

from typing import TypedDict, Unpack

class Movie(TypedDict):
  name: str
  year: int

def foo(**kwargs: Unpack[Movie]): ...
Enter fullscreen mode Exit fullscreen mode

8. @override Type Hinting
A novel addition in the typing module is the @override type annotation. This annotation helps indicate methods intended for overriding in object-oriented design. This aids typing tools like mypy in identifying code issues.

from typing import override

class Parent:
    def greet(self):

class Child(Parent):
    def greet(self):
Enter fullscreen mode Exit fullscreen mode

if a typo like changing Child.greet to Child.great occurs, mypy would likely generate non-zero output, indicating the absence of the expected overridden method from the base class.

9. New Type Defining
Python 3.12 introduces a new syntax for defining Type Aliases. This new syntax streamlines the process.


from typing import TypeAlias

  Players: TypeAlias = List[str]

  def list_players(players: Players) -> None: ...
Enter fullscreen mode Exit fullscreen mode


type Players = list[str]

def list_players(players: Players) -> None:
Enter fullscreen mode Exit fullscreen mode

This convention affects the appearance of functions and methods. For instance, the function scope can be structured as follows:


def analyze_data(data: List[str], values: List[float]) -> None:
Enter fullscreen mode Exit fullscreen mode


type Data = List[str]
type Values = List[float]

def process_data[data, values](data: Data, values: Values) -> None:
Enter fullscreen mode Exit fullscreen mode

The new function definition pattern follows: def NAME*TYPES -> TYPE. It's important to note that the types preceding the function name are confined to the function's scope.

Top comments (1)

sajjadrahman56 profile image
Sajjad Rahman

There is something wrong ?

Image description