Python 3.11 has been released for public usage on October 3rd, 2022. This article explores the significant performance increases as well as the new features added to the language.
BaseException
supports a set of positional arguments, as well as a method .with_traceback(tb)
that sets tb
as the new traceback for the exception. Following is an example of a built-in exception, ZeroDivisionException
, raised due to a division-by-zero on Python 3,9:The interpreter prints a traceback on the console saying that a division by zero occurred.
Traceback (most recent call last): file "<stdin>", line 1, in <module> ZeroDivisionError: division by zero
.py
files):# zero-div.py if __name__ == "__main__": print(3 / 0) # raises ZeeroDivisionError
Since Python modules usually include more than 1 line, the output will be more elaborate as it prints the line where the error occurred:
3 / 0
is the one responsible for raising ZeroDivisionError
. However, in certain situations where a single line may potentially raise the error from different statements, the traceback will not be very helpful for debugging. Let us consider the module below:# index-out-of-range.py if __name__ == "__main__": my_nested_list = [1, 2, 3, 4, [5, 6, 7, 8, 9, 10]] print(my_nested_list[4][6]) # index 6 is out of range
Running the code outputs:
The traceback is ambiguous as it is impossible to tell (just by looking at the error) which index is out of range.
index-out-of-range.py
module using Python 3.11:json
library.# config.toml language = "python" version = "3.11" release_date = "2022-10-22" features = ["exception_output", "exception_notes", "tomllib"]
# main.py import tomllib if __name__ == '__main__': # assuming that config.toml file lives in the same folder with open('config.toml', 'rb') as toml: config = tomllib.load(toml) print(f'{config["language"]} v{config["version"]} is released on {config["release_date"]} with the following features: {", ".join(config["features"])}')
tomllib
does not support writing TOML configurationsException
both as a generic exception class and a super-class for user-defined exceptions.Exception
subclass called ExceptionGroup
that groups several Exception
objects and prints them (beautifully) to the standard error, or wherever you configured your code to print them.ExceptionGroups
are generated:raise ExceptionGroup("my exception group", [ Exception('exception 1'), Exception('exception 2'), Exception('exception 3') ])
ExceptionGroup
takes a title/description as the first parameter and a list of Exception
objects as the second argument. Furthermore, since ExceptionGroup
is a subclass of Exception
, the list can also include an ExceptionGroup
(although I personally am not aware of any possible use case).The line of code outputs the following:
except*
syntax specifically to destructure the content of exception groups and handle them as you would any other exception:try: raise ExceptionGroup("group", [ValueError(4), IndexError(6)]) except* ValueError as e: print(f"ValueError caught: " + e.__str__()) except* IndexError as e: print("IndexError caught: " + e.__str__()) except* ArithmeticError as e: print("ArithmeticError caught: " + e.__str__())
which outputs:
Exception
class is the method .add_note(note)
which allows adding user-defined messages for more clarity:try: raise IndexError(6) except IndexError as e: e.add_note("'your_list' has only 4 items") raise
which outputs:
Self
Typetyping
since version 3.5, which allows developers to annotate (i.e. weakly type) variables in their code, and employ IDEs to intercept type mismatch ahead-of-time.Following are examples of type annotations in Python +3.5:
# Example of "primitive" types blog: str = "DevDog" year: int = 2022 pi: float = 3.14 # Example of "composite" types from typing import Optional, Union, List, Dict names: List[str] = ['Albert', 'Jack', 'Alex'] colors_to_french: Dict[str, str] = { 'red': 'rouge', 'green': 'vert', 'blue': 'bleu' } optional_var: Optional[str] = None # pre-3.10 number_or_string: Union[str, int] = 3 # +3.10 number_or_string: str | int = 'string is accepted as well' # function with return type def greet(name: str) -> str: return f"Hello ${name}"
typing
supported all kinds of type hints except for methods that return the class instance type. Therefore, Python 3.11 introduced the type Self
which indicates that a method returns an instance of its class:from typing import Self INTEREST_PERCENTAGE = 0.12 class Employee: def __init__(self, name, salary): self.name = name self.salary = salary def set_salary_with_interest(base_salary) -> Self: return Employee(self.name, base_salary - (base_salary * INTEREST_PERCENTAGE))
Python 3.11 is delivering key changes to the programming language that both improve the development experience and the overall performance of the language. Should you update your projects to 3.11? I believe this depends on how large your codebase is and which version you're running. Furthermore, if the migration costs and risks are minimal, it is worth the upgrade as you will be gaining a performance boost as well as better debugging tools.
Get the latest and trending sniffs in the software industry, straight to your inbox.
Blog owned by Houssem Eddine Zerrad. Posts and comments are owned by the poster
Copyright © 2023 DevDog - All Rights Reserved