Movatterモバイル変換


[0]ホーム

URL:


— FREE Email Series —

🐍 Python Tricks 💌

Python Tricks Dictionary Merge

🔒 No spam. Unsubscribe any time.

Browse TopicsGuided Learning Paths
Basics Intermediate Advanced
aialgorithmsapibest-practicescareercommunitydatabasesdata-sciencedata-structuresdata-vizdevopsdjangodockereditorsflaskfront-endgamedevguimachine-learningnewsnumpyprojectspythonstdlibtestingtoolsweb-devweb-scraping

Table of Contents

Recommended Course

Python 3.13: Cool New Features for You to Try

What's New in Python 3.13

53m · 12 lessons

Python 3.13: Cool New Features for You to Try

Python 3.13: Cool New Features for You to Try

byGeir Arne HjelleReading time estimate 40mintermediatepython

Table of Contents

Remove ads

Recommended Course

What's New in Python 3.13(53m)

Python 3.13 was published onOctober 7, 2024. This new version is a major step forward for the language, although several of the biggest changes are happening under the hood and won’t be immediately visible to you.

In a sense, Python 3.13 is laying the groundwork for some future improvements, especially to the language’s performance. As you read on, you’ll learn more about the background for this and dive into some new features that are fully available now.

In this tutorial, you’ll learn about some of the improvements in the new version, including:

  • Improvements made to theinteractive interpreter (REPL)
  • Clearer error messages that can help you fix common mistakes
  • Advancements done inremoving the global interpreter lock (GIL) and making Python free-threaded
  • The implementation of anexperimental Just-In-Time (JIT) compiler
  • A host of minor upgrades toPython’s static type system

If you want to try any of the examples in this tutorial, then you’ll need to use Python 3.13. The tutorialsPython 3 Installation & Setup Guide andHow Can You Install a Pre-Release Version of Python? walk you through several options for adding a new version of Python to your system.

Note: Python 3.13 was originally planned to be released on October 1, 2024. The developers found some issues during testing anddecided to push back the release to October 7.

In addition to learning more about the new features coming to the language, you’ll also get someadvice about what to consider before upgrading to the new version. Click the link below to download code examples demonstrating the new capabilities of Python 3.13:

Get Your Code:Click here to download the free sample code that shows you how to use the new features in Python 3.13.

Take the Quiz: Test your knowledge with our interactive “Python 3.13: Cool New Features for You to Try” quiz. You’ll receive a score upon completion to help you track your learning progress:


Python 3.13: Cool New Features for You to Try

Interactive Quiz

Python 3.13: Cool New Features for You to Try

In this quiz, you'll test your understanding of the new features introduced in Python 3.13. By working through this quiz, you'll review the key updates and improvements in this version of Python.

An Improved Interactive Interpreter (REPL)

If you run Python without specifying any script or code, you’ll find yourself insidePython’s interactive interpreter. This interpreter is informally called the REPL because it’s based on a read-evaluate-print loop. The REPLreads your input,evaluates it, andprints the result beforelooping back and doing the same thing again.

The Python REPL has been around for decades, and it supports an explorative workflow that makes Python a beginner-friendly language. Unfortunately, the interpreter has been missing several features you may have come to expect, including multiline editing and efficient pasting of code.

Note: Experienced Python developers often install a third-party interactive interpreter instead of relying on the built-in REPL. You can learn more about the alternatives in these tutorials:

You can also read more about alternative REPLs in theguide to the standard REPL.

Begin by starting the REPL. You can do this by typingpython in yourterminal. Depending on your setup, you may have to writepy,python3, or evenpython3.13 instead. One way to recognize that you’re using the new interpreter shipping with Python 3.13 is that the prompt consisting of three chevrons (>>>) is subtly colored:

The new REPL in Python 3.13 shows a colored prompt

One improvement is that you can now use REPL-specific commands without calling them with parentheses as if they are Python functions. Here are some of the commands and keyboard shortcuts you can use:

  • exit orquit: Exit the interpreter
  • clear: Clear the screen
  • help orF1: Access the help system
  • F2: Open the history browser
  • F3: Enter paste mode

You can learn more about these options inPython 3.13 Preview: A Modern REPL.

Recalling code you’ve written earlier has been cumbersome in the REPL before Python 3.13, especially if you’re working with a block of code spanning several lines. Traditionally, you’ve had to bring back each line one by one by repeatedly pressingUp. Now in 3.13, you can bring back the whole block of code with a singleUp keystroke.

To try this for yourself, enter the following code in your REPL:

Python
>>>numbers=range(3,13)>>>[...(number-3)**3fornumberinnumbers...ifnumber%2==1...][0, 8, 64, 216, 512]

You’re creating a somewhat complexlist comprehension that calculates an offset cube of a range of numbers, but only if the numbers are odd. The important part is that for readability, you split the list comprehension over several lines. Now try hitting thatUp key! The interpreter recalls all four lines at once, and you can continue to use your arrow keys to move around inside of the expression.

You can make changes to your code and run it again. To execute the updated code, you need to move your cursor to the end of the last line in the code block. If you pressEnter inside the expression, you’ll create a new empty line instead:

The ability to recall and edit multiline statements is a huge time-saver and will make you more efficient when working with the REPL.

Another convenience coming in Python 3.13 is proper support for pasting code. In Python 3.12 and earlier, you’d need to make sure that your code doesn’t contain any blank lines before you could copy and paste it. In the new version, pasted code is treated as a unit and executes just as it would inside a script.

This makes it more convenient to use the REPL to interactively tweak and debug your scripts. As an example, say that you want to write a script that can printrandom numbers, maybe toact as dice in a tabletop game you’re playing:

Pythonroll_dice.py
importrandomnum_faces=6print("Hit enter to roll die (q to quit, number for # of faces) ")whileTrue:roll=input()ifroll.lower().startswith("q"):breakifroll.isnumeric():num_faces=int(roll)result=random.randint(1,num_faces)print(f"Rolling a d{num_faces:<2d} -{result:2d}")

If you try to copy and paste this code into an older REPL, then it won’t work. The blank line inside thewhile loop causes issues. You enter an infinite loop that seemingly doesn’t do anything. To stop the loop, you can typeq and hitEnter or pressCtrl+C.

In Python 3.13, pasting works without a hitch:

Python
>>>importrandom......num_faces=6......print("Hit enter to roll die (q to quit, number for # of faces) ")...whileTrue:...roll=input()...ifroll.lower().startswith("q"):...break...ifroll.isnumeric():...num_faces=int(roll)......result=random.randint(1,num_faces)...print(f"Rolling a d{num_faces:<2d} -{result:2d}")...Hit enter to roll die (q to quit, number for # of faces)13Rolling a d13 -  10Rolling a d13 -   5Rolling a d13 -   3q

Note that the prompt displays as three dots (...) for all the code that you paste, indicating that it’s all part of one code unit. In this example, you choose to roll ad13, a thirteen-sided die, three times.

Note: You can learn more about Python’s new REPL in the dedicated tutorial,Python 3.13 Preview: A Modern REPL.

Another arena where your Python developer experience gets a small boost in Python 3.13 is through improved error messages, which you’ll learn about next.

Better Error Messages

The REPL is great to work with when you first start using Python, and another feature you quickly run into is Python’s error messages. It hasn’t always felt like the error messages were trying to help you. However, over the last several releases, they’ve gotten friendlier and more helpful:

Python 3.13 continues this great tradition of enhancing your developer experience. In this release, color is added to the tracebacks shown when you encounter a runtime error. Additionally, more kinds of error messages provide you with suggestions on how to fix errors. You’ll look closer at these in this section.

First, you’ll provoke Python and create a runtime error to get a glimpse of the colored tracebacks. Open your REPL and defineinverse() as follows:

Python
>>>definverse(number):...return1/number...

Theinverse() function calculates the multiplicative inverse of a number. One issue thatinverse() doesn’t account for, is that zero doesn’t have an inverse. In your function, you see this becauseinverse(0) raises aZeroDivisionError:

Tracebacks are colored in Python 3.13

Your tracebacks now have colors, with important information highlighted in red and purple. In general, this should make error messages easier to read and understand.

However, if you don’t like the colors, you canturn them off by setting thePYTHON_COLORS environment variable to0.

Since Python 3.10, error messages have included aDid you mean suggestion feature that can help you out if you misspell a keyword, function name, or even a module name. In Python 3.13, the suggestions are expanded to include keyword arguments in function calls. Say that you’re trying to sort a list of numbers in descending order:

Python
>>>numbers=[2,0,2,4,1,0,0,1]>>>sorted(numbers,reversed=True)Traceback (most recent call last):  File"<python-input-1>", line1, in<module>sorted(numbers,reversed=True)~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^TypeError:sort() got an unexpected keyword argument 'reversed'.           Did you mean 'reverse'?>>>sorted(numbers,reverse=True)[4, 2, 2, 1, 1, 0, 0, 0]

You try to usereverse=True to sort the numbers in reverse order. At first, you make a typo and call the argumentreversed with ad at the end. Python notices this and helpfully suggests that you meantreverse.

Some of the advanced features in Python are backed by simple mechanisms. For example, to create your own Python module, you only need to create a file named with a.py suffix. This is great for exploring the language, but also opens the door for things to go wrong in interesting ways.

The following scenario is something you’ve probably run into. Recall the dice-rolling script fromearlier. Say that you had called the filerandom.py instead:

Pythonrandom.py
importrandomnum_faces=6print("Hit enter to roll die (q to quit, number for # of faces) ")whileTrue:roll=input()ifroll.lower().startswith("q"):breakifroll.isnumeric():num_faces=int(roll)result=random.randint(1,num_faces)print(f"Rolling a d{num_faces:<2d} -{result:2d}")

Your game is waiting on the table and you’re excited to start rolling the dice. Run the script and let randomness unfold:

Shell
$pythonrandom.pyHit enter to roll die (q to quit, number for # of faces)Traceback (most recent call last):  File "/home/realpython/random.py", line 1, in <module>    import random  File "/home/realpython/random.py", line 13, in <module>    result = random.randint(1, num_faces)             ^^^^^^^^^^^^^^AttributeError: module 'random' has no attribute 'randint' (consider                renaming '/home/realpython/random.py' since it has the same                name as the standard library module named 'random' and the                import system gives it precedence)

Error messages likemodule ‘random’ has no attribute ‘randint’ has confused Python developers for decades. Surely,randint() is one of the functions in therandom module!

In Python 3.13, you no longer need to scratch your head, as the error message points out what’s likely the problem. When you createdrandom.py, you created a newrandom module that shadows the one in the standard library. To fix the problem, you should rename your script.

Note: You can use another workaround to make the example work. If you add the-P option and runpython -P random.py, then Python won’t include your current directory in the paths that Python searches during imports, and your script won’t hide therandom standard-library module.

Renamerandom.py back toroll_dice.py and run it again:

Shell
$pythonroll_dice.pyHit enter to roll die (q to quit, number for # of faces)Rolling a d6  -   3Rolling a d6  -   1Rolling a d6  -   320Rolling a d20 -  13q

Your script is no longer hidingrandom from the standard library. In the example above, you first roll a regular six-sided die three times, before switching to a twenty-sided die.

You’ll see a similar error message if you happen to shadow a third-party package as well. In general, you should be careful with naming your top-level Python files the same as libraries that you plan to import.

Note: Naming clashes are less of an issue in submodules that are part of a package. For example, you can create a package forserializing data that can serialize to different formats likeCSV andJSON.

Inside the package, you can keep format-specific code in files namedcsv.py andjson.py without worrying that these will shadowcsv andjson in the standard library. This is because these files are not top-level. Instead, you access them withimport serialize_package.csv orfrom serialyze_package import csv.

The continued work on improving your developer experience helps Python defend its position as a beginner-friendly language.

Free-Threaded Python: Look Ma, No GIL

High-level languages like Python provide some conveniences for you as a developer. For example, you can trust that Python will handle memory for you. You don’t need to worry about allocating memory before initializing a data structure, and you don’t need to remember to free the memory when you’re done working with it.

Note: For an in-depth exploration of the free-threading feature, check outPython 3.13 Preview: Free Threading and a JIT Compiler.

Another programming problem that Python helps you with is making sure that your code is thread-safe. Simply put, for code to be thread-safe, it needs to ensure that two different threads of execution don’t update the same part of memory at the same time.

Python’s solution to this is a bit heavy-handed. It uses a global interpreter lock (GIL) to ensure that only one thread accesses the memory at a time. For most operations, a thread must first acquire the GIL. Because this lock is global—there’s only one GIL—most Python programs are effectively single-threaded, even when they’re running on modern hardware with several CPUs available.

Note: Many libraries that are written in C, includingNumPy, are able to bypass the GIL by handling thread safety on their own. Such code can often take advantage of computers with multiple cores.

Historically, the GIL proved to be a simple and effective solution to addingbindings to C libraries that weren’t thread-safe. The GIL has likely played a significant role in Python’s rise in popularity as a programming language.

As the number of CPUs available in computers has increased over the years, the GIL has become more of a troublemaker than a hero. The community has attempted to remove the GIL from the language several times. The most recent attempt, initialized by Sam Gross, is by far the most promising. In fact, you can set up a specialfree-threaded version of Python 3.13 that doesn’t have a global interpreter lock.

Trying out the free-threaded version of Python requires some time and effort. You may be able to get a version from your platform’s regular distribution channel. If not, you can either download Python’s source code and build it yourself, or run Python through Docker. For more information, seeGet Your Hands on the New Features in the free threading preview.

The free-threaded Python executable is typically namedpython3.13t with at suffix. Once you have your hands on a free-threaded version of Python, you can choose to enable or disable the GIL each time you run Python:

Shell
$CODE='import pyfeatures; print(pyfeatures.FreeThreading())'$python3.13-c"$CODE"Free Threading: unsupported$python3.13t-c"$CODE"Free Threading: enabled ✨$python3.13t-Xgil=1-c"$CODE"Free Threading: disabled

You enable the GIL and turn off free threading by setting-X gil=1. Thepyfeatures module needed to run the above code is available in the downloadable materials. It contains functionality for detecting the status of free threading.

Note that enabling the GIL on the free-threaded version isn’t completely equivalent to running the standard version of Python. At least in early versions of Python 3.13, running the free-threaded version with the GIL enabled shows some issues with performance:

Performance of Python 3.13 on an All-in-One Computer
Performance of Python 3.13 on an All-in-One Computer

This particular benchmark is run on a computer with four CPUs. Note that the graph for free-threaded Python with the GIL disabled is close to flat for the first four threads. This is very promising, as it indicates that this version of Python is able to take advantage of all cores on the computer.

If you’re interested in learning more about this benchmark, then go ahead and readMeasure the Performance Improvements of Python 3.13 which goes more in-depth on the performance of free-threaded Python.

Note: You can learn more about Python’s global interpreter lock inWhat is the Python Global Interpreter Lock? andBypassing the GIL for Parallel Processing in Python.

Removing the GIL is a massive undertaking that will hopefully make Python more performant in the future. In the next section, you’ll look at another feature aimed at speeding up Python.

Experimental JIT Compiler

Python is an interpreted language. This is in contrast to languages like C and Rust, which are all compiled languages. In an interpreted language, you need a runtime like a Python interpreter to run your code. Compiled code, on the other hand, can typically be run directly on your system.

There are advantages and disadvantages to both models. Python is often a language that’s efficient for developers, where new code can be tested quickly. But, the code itself may run slower than equivalent compiled code.

A just-in-time, or JIT, compiler provides a kind of middle ground, where the interpreter may choose to compile some code while a program is running in order to speed it up. In Python 3.13, there’s a new, experimental JIT compiler. The fact that it’s experimental means that it’s present in Python’s source code, but it’s not enabled by default.

If you want to try out the JIT compiler, you need to set up a special version of Python 3.13 with the JIT enabled. This is similar to what you need to do to try out free-threaded Python, although with different build flags.

Note: Check outBuild Python With Free Threading and JIT Support to learn how to build Python with JIT support.

Python’s JIT compiler is based on an algorithm calledcopy-and-patch. The interpreter will look for patterns in your code that match pre-compiled templates and fill in the machine code with specific information like memory addresses of variables.

JIT compilation can be effective and give better performance in code where the same operation is repeated over and over again, giving the JIT compiler time to analyze and translate your code. In one benchmark, which repeatedly calculated theFibonacci series, you can see a small improvement in performance with the JIT:

Performance Python 3.13 with the JIT Compiler
Performance of Python 3.13 on an All-in-One Computer

In this benchmark, Python 3.13 with the JIT enabled is faster than both Python 3.12 and regular Python 3.13. However, the JIT isn’t ready for everyday use yet, and you should limit yourself to experimenting with it. Hopefully, the JIT will have more impact in future Python releases.

To learn more about the above benchmark, as well as the new experimental JIT compiler, dig intoPython 3.13 Preview: Free Threading and a JIT Compiler.

Improvements to Static Typing

While Python is a dynamically typed language, you can add static type information in optionaltype hints. You can run a separate type checker likemypy orPyright to validate your code, or you can rely on your IDE to advise you about issues.

The foundations of Python’s static type system were defined inPEP 484 and introduced in Python 3.5. In November 2023,PEP 729 established theTyping Council and formalized the type system through atyping specification.

The Typing Council governs the Python type system and aims to make it useful, usable, and stable. It maintains the typing specification and advisesPython’s Steering Council ontyping-related PEPs. The initial members of the Typing Council are:

In addition to providing more clarity in the governance of Python’s type system, the community has implemented some code-related changes as well. The following PEPs have been accepted for Python 3.13:

  • PEP 696: Type defaults for type parameters
  • PEP 742: Narrowing types withTypeIs
  • PEP 705:TypedDict: Read-only items
  • PEP 702: Marking deprecations using the type system

In this tutorial, you’ll focus on the first two changes: type defaults and improved type narrowing. If you’re interested in learning more about read-onlyTypedDict items or deprecations, have a look at their respective PEPs or check out the downloadable materials. The latter contains examples that you can play with on your own.

Similar to other features in the language, typing improvements are tied to a specific version of Python. However, they also require that the type checker you’re using implements the new feature. When possible, new features are backported to older Python versions through thetyping_extensions library. For example, you can useTypeIs on, say, Python 3.10 by importing fromtyping_extensions instead oftyping.

Note: In this section, you’ll usePyright as your type checker. You can installPyright into yourvirtual environment usingpip:

Shell
(venv)$python-mpipinstallpyright

If you’re usingVisual Studio Code, then you can use Pyright inside the editor through thePylance extension. You may need to activate it by setting thePython › Analysis: Type Checking Mode option in your settings.

Python 3.12 introduced anew syntax for type generics. Ageneric type is one that’s parametrized by another type. For example, alist is a generic type as you can have a list of strings or a list of integers. Both are lists, but they are parametrized by different types, namely strings and integers.

Traditionally, you’ve needed to explicitly define type variables usingTypeVar. Since Python 3.12, you can declare type variables in a more compact[T] syntax using square brackets:

Pythongeneric_queue.py
fromcollectionsimportdequeclassQueue[T]:def__init__(self)->None:self.elements:deque[T]=deque()defpush(self,element:T)->None:self.elements.append(element)defpop(self)->T:returnself.elements.popleft()

In this example, you create a genericqueue based ondeque. You can use the queue as follows:

Python
>>>fromgeneric_queueimportQueue>>>string_queue=Queue[str]()>>>string_queue.push("three")>>>string_queue.push("thirteen")>>>integer_queue=Queue[int]()>>>integer_queue.push(3)>>>integer_queue.push(13)

You declare thatstring_queue will be a queue with string elements by adding[str] in square brackets when you create the instance. Similarly,[int] specifies thatinteger_queue will have integer elements. If you leave out the square brackets and callQueue() directly, then your queue can have elements of arbitrary type.

You can now specify atype default for these kinds of generic classes. This default will be assumed when you don’t explicitly define a type:

Pythongeneric_queue.py
fromcollectionsimportdequeclassQueue[T=str]:def__init__(self)->None:self.elements:deque[T]=deque()defpush(self,element:T)->None:self.elements.append(element)defpop(self)->T:returnself.elements.popleft()string_queue=Queue()reveal_type(string_queue)integer_queue=Queue[int]()reveal_type(integer_queue)

You define the type default similarly to how you specify default arguments for functions. The syntax[T=str] means that if the type ofT isn’t specified, then it’ll bestr. To confirm this, you use the specialreveal_type(). This function is understood by your type checker, but will fail if you run your code:

Shell
$pyright--pythonversion3.13generic_queue.pygeneric_queue.py  generic_queue.py:15:13 - information: Type of "string_queue" is "Queue[str]"  generic_queue.py:18:13 - information: Type of "integer_queue" is "Queue[int]"0 errors, 0 warnings, 2 informations

When you run Pyright on your code,reveal_type() confirms thatstring_queue is a queue of strings, even if you haven’t explicitly specified it.

Note: You can also use type defaults with the traditionalTypeVar syntax, by writingT = TypeVar("T", default=str). See thetyping specification for more information.

Type defaults is a small addition that can make working with generics more convenient.

Python 3.10 introducedtype guards. These allow you to narrow union types. Consider the following example of a recursively defined tree structure:

Pythontree.py
 1fromtypingimportTypeGuard 2 3typeTree=list[Tree|int] 4 5defis_tree(obj:object)->TypeGuard[Tree]: 6returnisinstance(obj,list)andall( 7is_tree(elem)orisinstance(elem,int)foreleminobj 8) 910defget_left_leaf_value(tree_or_leaf:Tree|int)->int:11ifis_tree(tree_or_leaf):12returnget_left_leaf_value(tree_or_leaf[0])13else:14returntree_or_leaf

Here,is_tree() acts as a type guard that can identify trees. In your code, aTree is a nested list of integers. The recursiveget_left_leaf_value() function takes either aTree or a single integer. However, after checkingis_tree(), you can safely access the first element of the tree on line 12.

Type guards have some limitations where they don’t work well with generic types and they only provide positive guarantees. The latter means that the type checker isn’t allowed to do any type narrowing if the type guard returnsFalse.

In the example above, this means that for a type checker,tree_or_leaf on line 14 is still of typeTree | int:

Shell
$pyright--pythonversion3.13tree.pytree.py  tree.py:14:16 - error: Type "Tree | int" isn't assignable to return type "int"    Type "Tree | int" is not assignable to type "int"      "list[Tree | int]" is not assignable to "int" (reportReturnType)1 error, 0 warnings, 0 informations

Here, your type checker complains about the type in your secondreturn statement. However, since this is in theelse branch, you know thattree_or_leaf is anint. To convince your type checker of this, you’d need another type guard for integers.

TypeIs is similar toTypeGuard but it provides more type narrowing information to the type checker, and solves the issue with the example above. In many cases, you can useTypeIs as a drop-in replacement forTypeGuard:

Pythontree.py
 1fromtypingimportTypeIs 2 3typeTree=list[Tree|int] 4 5defis_tree(obj:object)->TypeIs[Tree]: 6returnisinstance(obj,list)andall( 7is_tree(elem)orisinstance(elem,int)foreleminobj 8) 910defget_left_leaf_value(tree_or_leaf:Tree|int)->int:11ifis_tree(tree_or_leaf):12returnget_left_leaf_value(tree_or_leaf[0])13else:14returntree_or_leaf

You’ve replacedTypeGuard withTypeIs. This provides more information to the type checker. In particular, it knows thattree_or_leaf can’t be aTree if you enter theelse branch on line 13, sotree_or_leaf must be an integer in this case. You can confirm this by running Pyright:

Shell
$pyright--pythonversion3.13tree.py0 errors, 0 warnings, 0 informations

You can read more about type narrowing and the difference betweenTypeGuard andTypeIs in thetyping specification.

While Python’s type system is constantly evolving, most of the new features are actually incremental improvements on existing capabilities. This reflects that static typing in Python is fairly mature at this point.

Other Pretty Cool Features

You’ve seen the highlights of what’s coming in Python 3.13. However, each new release of Python contains tons of little changes contributed by enthusiastic developers. In this section, you’ll check out some of the improvements that don’t necessarily get the big headlines.

A Random Command Line

Python comes with several tools baked in. A couple of the more famous ones arejson.tool andhttp.server. You access these through Python’s-m switch:

Shell
$python-mjson.tooldog_friend.json{    "name": "Frieda",    "age": 8}$python-mhttp.serverServing HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

You can usejson.tool to formatJSON files and make them more convenient to read. Withhttp.server, you can quickly run a local HTTP server.

Python 3.13 adds a command-line interface to therandom module:

Shell
$python-mrandomusage: random.py [-h] [-c CHOICE [CHOICE ...] | -i N | -f N] [input ...]positional arguments:  input                 if no options given, output depends on the input                            string or multiple: same as --choice                            integer: same as --integer                            float: same as --floatoptions:  -h, --help            show this help message and exit  -c, --choice CHOICE [CHOICE ...]                        print a random choice  -i, --integer N       print a random integer between 1 and N inclusive  -f, --float N         print a random floating-point number between 0 and N

You can quickly create a random number or make a random choice by callingpython -m random. Depending on your input you’ll get one of three results back:

  • If you pass a list of elements, you’ll get one random element from the list.
  • If you pass an integerN, you’ll get a random integer between 1 andN.
  • If you pass a floatx, you’ll get a random float between 0 andx.

Try it out for yourself:

Shell
$python-mrandomOsloBerlinLondonKrakowBelgradeGrazKrakow$python-mrandom63$python-mrandom6.03.132801224231027

Whether you want to plan your next random getaway, simulate some dice rolls, or just need a random number, you can now turn to therandom module for some quick help. By default, the kind of random result you get depends on what you pass in. However, you can also use options like--choice,--integer, and--float to be explicit:

Shell
$python-mrandom--float61.4284991504686064

Here, you get a random floating-point number even if you pass in an integer as a limit because you specified--float. This command-line interface isn’t advanced, but it can be a quick help if you need something random.

Newcopy.replace() for Modifying Immutable Objects

There are several advantages to working withimmutable objects. Since an immutable object can’t change after you’ve created it, it’s straightforward to reason about its state. You can also readilycache immutable objects or use them in distributed contexts.

Python comes with several immutable data structures, includingtuples,frozen sets, andfrozen data classes. If you represent your data with immutable data structures, then you can still change the state of your data by creating new immutable objects that may share one or more fields with the original.

Consider the following example, modeling a person and their current Python version:

Python
>>>fromtypingimportNamedTuple>>>classPerson(NamedTuple):...name:str...place:str...version:str...>>>person=Person(name="Geir Arne",place="Oslo",version="3.12")

Now, say that yourperson upgrades to the latest Python version. IfPerson had been mutable, you could writeperson.version = "3.13". However, that’s not possible with anamed tuple. Instead, you create a newPerson object and pointperson to that new object:

Python
>>>person=Person(name=person.name,place=person.place,version="3.13")>>>personPerson(name='Geir Arne', place='Oslo', version='3.13')

You create a newPerson object with the same name and location as before, but update the Python version. This works but can become hard to read, write, and maintain if your data structure has many fields.

Some built-in immutable classes have support for this use case with a dedicated method. For example, you can copydate anddatetime objects, replacing one or more fields as you do so:

Python
>>>fromdatetimeimportdate>>>today=date.today()>>>todaydatetime.date(2024, 9, 30)>>>today.replace(day=1)datetime.date(2024, 9, 1)>>>today.replace(month=12,day=24)datetime.date(2024, 12, 24)

You use.replace() to calculate the first of the current month, or Christmas Eve this year.

In Python 3.13, a newreplace() function is added to thecopy module to consistently provide the same functionality to many immutable data structures. You can usecopy.replace() to re-create the examples above:

Python
>>>importcopy>>>person=Person(name="Geir Arne",place="Oslo",version="3.12")>>>copy.replace(person,version="3.13")Person(name='Geir Arne', place='Oslo', version='3.13')>>>copy.replace(today,day=1)datetime.date(2024, 9, 1)

If you don’t provide a new value to a field withreplace(), then its original value is kept. When you upgrade the Python version, you only need to specifyversion and not the other fields. As before, the original object doesn’t change:

Python
>>>personPerson(name='Geir Arne', place='Oslo', version='3.12')

You’d need to explicitly updateperson if that’s what you want.

You can usereplace() to modify data classes in addition to named tuples. You can also add a.__replace__() special method if you wantreplace() to work with your custom class. You’ll find an example of how this works in the downloadable materials.

Improved Globbing of Files and Directories

Python’spathlib module has many tools for working with paths and files consistently across operating systems. For example, you canlist files and directories using.glob():

Python
>>>frompathlibimportPath>>>Path("music")PosixPath('music')>>>forpathinPath("music").glob("*"):...print(path)...music/operamusic/rap

In this example, you explore themusic/ directory on your computer. It contains two items,opera andrap.

Note: Themusic/ directory has the following structure:

music/│├── opera/│   ├── flower_duet.txt│   ├── habanera.txt│   └── nabucco.txt│└── rap/    ├── bedlam_13-13.txt    └── fight_the_power.txt

You can find themusic/ directory in the downloadable materials if you want to follow along yourself.

The.glob() method uses specialglob patterns which have been used to represent sets of filenames since the 1970s. You use special wildcard characters like* and? where* matches any number of any characters, while? matches any single character.

For example,*.py matches any filename that ends with.py. Similarly,python3.1? matches names likepython3.12,python3.13, andpython3.1X, but notpython3.1 orpython3.100.

One special pattern is the globstar (**) which is available in many terminal shells. It matches all files and directories recursively. You can exploremusic/ in Bash withls:

Shell
$lsmusic/**music/opera:flower_duet.txt  habanera.txt  nabucco.txtmusic/rap:bedlam_13-13.txt  fight_the_power.txt

Usingls music/**, you list all directories and files insidemusic/. While Python has supported**, its behavior has been inconsistent with other tools. In Python 3.12, you can observe the following:

Python
>>>forpathinPath("music").glob("**"):...print(path)...musicmusic/operamusic/rap>>>forpathinPath("music").glob("**/*"):...print(path)...music/operamusic/rapmusic/opera/nabucco.txtmusic/opera/flower_duet.txtmusic/opera/habanera.txtmusic/rap/bedlam_13-13.txtmusic/rap/fight_the_power.txt

Using the globstar only lists directories. If you want to list both directories and files, you need to use the extended**/* pattern.

In Python 3.13, the behavior of** is changed to be consistent with traditional tools:

Python
>>>forpathinPath("music").glob("**"):...print(path)...musicmusic/operamusic/rapmusic/rap/bedlam_13-13.txtmusic/rap/fight_the_power.txtmusic/opera/nabucco.txtmusic/opera/flower_duet.txtmusic/opera/habanera.txt

Using** as your glob pattern now lists both directories and files. If you need to constrain your pattern to only show directories, then you can be explicit and add a slash (/) at the end of your pattern:

Python
>>>forpathinPath("music").glob("**/"):...print(path)...musicmusic/operamusic/rap

You add a slash (/) at the end of your pattern to make.glob() only return directories.

Typically, you’ll use.glob() throughpathlib. But the functionality is also available in theglob module. Python 3.13 adds a new function,glob.translate() that you can use to convert a glob pattern to a regular expression (regex).

Regular expressions are patterns that you can use to search and match general strings. They are more general andmore powerful than glob patterns, but they’re alsomore complex. If you need more flexibility when working with a glob pattern, you can try to translate it into a regular expression:

Python
>>>importglob>>>pattern=glob.translate("music/**/*.txt")>>>pattern'(?s:music/(?!\\.)[^/]*/(?!\\.)[^/]*\\.txt)\\Z'

You translate the glob pattern that matches any.txt file nested insidemusic/ into a regular expression. You can then match the regex pattern against any string usingre.match():

Python
>>>importre>>>re.match(pattern,"music/opera/flower_duet.txt")<re.Match object; span=(0, 27), match='music/opera/flower_duet.txt'>>>>re.match(pattern,"music/progressive_rock/")>>>re.match(pattern,"music/progressive_rock/fandango.txt")<re.Match object; span=(0, 35), match='music/progressive_rock/fandango.txt'>

In this example, your two file paths match the pattern, while the directory path doesn’t.

Pathlib now usesglob.translate() internally for several operations. This comes with asmall performance boost as directories can bewalked faster andPath objects can be smaller.

Naked Docstrings

Python stores inline documentation indocstrings. You can access these through thehelp system. At runtime, you can also access docstrings through.__doc__:

Python
>>>importdataclasses>>>@dataclasses.dataclass...classPerson:..."""Model a person with a name, location, and Python version."""...name:str...place:str...version:str...>>>Person.__doc__'Model a person with a name, location, and Python version.'

You’ve added a docstring toPerson by writing a text string immediately after theclass statement. It’s a convention to use triple-quoted strings for docstrings. You can access the docstring by looking at the.__doc__ special attribute.

Because docstrings are typically written inside a function, method, or class definition, they’ll contain a fair bit of spaces. The indentation Python requires is reflected in the docstring. On Python 3.12, you’ll see something like this:

Python
>>>importdataclasses>>>dataclasses.replace.__doc__'Return a new object replacing specified fields with new values.\n\n    This is especially useful for frozen classes.  Example usage::\n\n       @dataclass(frozen=True)\n      class C:\n          x: int\n           y: int\n\n      c = C(1, 2)\n      c1 = replace(c, x=3)\n       assert c1.x == 3 and c1.y == 2\n    '>>>len(dataclasses.replace.__doc__)299>>>print(dataclasses.replace.__doc__)Return a new object replacing specified fields with new values.    This is especially useful for frozen classes.  Example usage::      @dataclass(frozen=True)      class C:          x: int          y: int      c = C(1, 2)      c1 = replace(c, x=3)      assert c1.x == 3 and c1.y == 2

Note that every line in the docstring, except the first one, contains between four and ten leading spaces. In Python 3.13, docstrings are stripped! They’re stored with the common leading whitespace removed. Rerun the same example in the newest Python version:

Python
>>>importdataclasses>>>dataclasses.replace.__doc__'Return a new object replacing specified fields with new values.\n\nThis is especially useful for frozen classes.  Example usage::\n\n   @dataclass(frozen=True)\n  class C:\n      x: int\n      y: int\n\n   c = C(1, 2)\n  c1 = replace(c, x=3)\n  assert c1.x == 3 and c1.y == 2\n'>>>len(dataclasses.replace.__doc__)263>>>print(dataclasses.replace.__doc__)Return a new object replacing specified fields with new values.This is especially useful for frozen classes.  Example usage::  @dataclass(frozen=True)  class C:      x: int      y: int  c = C(1, 2)  c1 = replace(c, x=3)  assert c1.x == 3 and c1.y == 2

In this case, four spaces have been removed from every line except the first one. This is a small optimization that means that docstrings take up less memory than before.

If you have code that relies on the exact value of.__doc__, you should test it to make sure it still behaves as expected in Python 3.13.

So, Should You Upgrade to Python 3.13?

You’ve seen several of the features coming in Python 3.13. There are even many more that you can read about in thePython changelog. Improved features not covered in this tutorial include:

Additionally, Python’sannual release cycle has beenrevised toextend full support from eighteen months to a full two years. Each release will still get security fixes for five years:

The life cycle of Python releases
Click the image to see more details.

The diagram shows the life cycles of Python 3.13 and the upcoming 3.14 and 3.15.

Note: The garbage collector was rewritten to beincremental in pre-release versions of Python 3.13. This reduced maximum pause times when collecting larger memory heaps. However, it also caused much worse performance insome examples. The new garbage collector implementation was thereforetaken out again and won’t be part of the final 3.13 version.

So, having seen all these new improvements, should you upgrade to Python 3.13? Like for every release, the answer is a clear and loudit depends!

There isn’t any big reason not to update yourlocal environment that you use for exploring the language. The new REPL and improved error messages are nice quality-of-life upgrades and you might see some small performance improvements. That said, if you don’t use the built-in REPL, there aren’t any super attractive features that you need to jump on either.

If you’remaintaining a library, especially one that uses Python’s C-API, you should start testing with Python 3.13, both the regular version and the free-threaded one. It’s important to surface any bugs in the implementation as soon as possible. Adding a bug report is a great contribution to the language. Your library may also need some updates to be compatible with free threading.

For code that’srunning in production, you should be as diligent as ever with testing your code on Python 3.13 before upgrading your runtime. While a lot of testing has been done since Python 3.13 reached beta in May 2024, there are always bugs that surface after the official release. For critical code, you’ll be fine with running on Python 3.12 until its full support ends inApril 2025.

A question that’s independent of when you upgrade your Python is when you should start using the new features. Again, it depends on your code and your situation.

This time around, there aren’t any big syntax changes, likef-strings, thewalrus operator, or thematchcase statement in the past. Instead, there are some functions, likecopy.replace() andglob.translate() that will only be available for you on Python 3.13.

If youwork on an application where you can control the running environment, you can use Python 3.13 features as soon as you’ve upgraded the environment. If you work on a team, then you need to make sure everyone’s on board and upgraded before you introduce any incompatible syntax.

If youwrite a library that others use, then you don’t know which version of Python they’ll be using. In this case, it pays off to be more conservative and ideally support each version throughout its lifetime. Python 3.8 reaches end-of-support inOctober 2024, so you could start looking at requiring Python 3.9 as your minimal version.

Moving forward, there will bebugfix releases of Python 3.13. These are planned to be released approximately every two months. If you start using Python 3.13, you should stay up-to-date with the bugfix updates, and upgrade your environment as they become available.

Conclusion

A new Python release is always great news! You’ve been on a tour of the features and improvements that have been updated in Python 3.13. Send some appreciation to all the volunteers that put time and effort into the development!

In this tutorial, you’ve seen new features and improvements, like:

  • Improvements made to theinteractive interpreter (REPL)
  • Clearer error messages that can help you fix common mistakes
  • Advancements done inremoving the global interpreter lock (GIL) and making Python free-threaded
  • The implementation of anexperimental Just-In-Time (JIT) compiler
  • A host of minor upgrades toPython’s static type system

You probably won’t be able to take advantage of the new features right away, but you should install Python 3.13 on your system and play with it.

Get Your Code:Click here to download the free sample code that shows you how to use the new features in Python 3.13.

Take the Quiz: Test your knowledge with our interactive “Python 3.13: Cool New Features for You to Try” quiz. You’ll receive a score upon completion to help you track your learning progress:


Python 3.13: Cool New Features for You to Try

Interactive Quiz

Python 3.13: Cool New Features for You to Try

In this quiz, you'll test your understanding of the new features introduced in Python 3.13. By working through this quiz, you'll review the key updates and improvements in this version of Python.

Recommended Course

What's New in Python 3.13(53m)

🐍 Python Tricks 💌

Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

AboutGeir Arne Hjelle

Geir Arne is an avid Pythonista and a member of the Real Python tutorial team.

» More about Geir Arne

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

MasterReal-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

MasterReal-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.


Looking for a real-time conversation? Visit theReal Python Community Chat or join the next“Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Topics:intermediatepython

Related Courses:

Related Tutorials:

Keep reading Real Python by creating a free account or signing in:

Already have an account?Sign-In

Almost there! Complete this form and click the button below to gain instant access:

Python 3.13: Cool New Features for You to Try

Python 3.13: Cool New Features for You to Try (Sample Code)

🔒 No spam. We take your privacy seriously.


[8]ページ先頭

©2009-2026 Movatter.jp