4242 This saves the maintainer the effort of going through the Mercurial log
4343 when researching a change.
4444
45- This article explains the new features in Python 3.8, compared to 3.7.
45+ :Editor: Raymond Hettinger
4646
47+ This article explains the new features in Python 3.8, compared to 3.7.
4748For full details, see the:ref: `changelog <changelog >`.
4849
49- ..note ::
50+ Prerelease users should be aware that this document is currently in
51+ draft form. It will be updated as Python 3.8 moves towards release, so
52+ it's worth checking back even after reading earlier versions. Some
53+ notable items not yet covered are:
5054
51- Prerelease users should be aware that this document is currently in draft
52- form. It will be updated substantially as Python 3.8 moves towards release,
53- so it's worth checking back even after reading earlier versions.
55+ *:pep: `578 ` - Runtime audit hooks for potentially sensitive operations
56+ * ``python -m asyncio `` runs a natively async REPL
5457
55- Some notable items not yet covered here :
58+ .. testsetup : :
5659
57- *:pep: `578 ` - Runtime audit hooks for potentially sensitive operations
58- * ``python -m asyncio `` runs a natively async REPL
59- * ...
60+ from datetime import date
61+ from math import cos, radians
62+ import re
63+ import math
6064
6165
6266Summary -- Release highlights
@@ -76,12 +80,43 @@ New Features
7680Assignment expressions
7781----------------------
7882
79- There is new syntax (the "walrus operator", ``:= ``) to assign values
80- to variables as part of an expression. Example::
83+ There is new syntax ``:= `` that assigns values to variables as part of a larger
84+ expression. It is affectionately known as "walrus operator" due to
85+ its resemblance to `the eyes and tusks of a walrus
86+ <https://en.wikipedia.org/wiki/Walrus#/media/File:Pacific_Walrus_-_Bull_(8247646168).jpg> `_.
87+
88+ In this example, the assignment expression helps avoid calling
89+ :func: `len ` twice::
8190
8291 if (n := len(a)) > 10:
8392 print(f"List is too long ({n} elements, expected <= 10)")
8493
94+ A similar benefit arises during regular expression matching where
95+ match objects are needed twice, once to test whether a match
96+ occurred and another to extract a subgroup::
97+
98+ discount = 0.0
99+ if (mo := re.search(r'(\d+)% discount', advertisement)):
100+ discount = float(mo.group(1)) / 100.0
101+
102+ The operator is also useful with while-loops that compute
103+ a value to test loop termination and then need that same
104+ value again in the body of the loop::
105+
106+ # Loop over fixed length blocks
107+ while (block := f.read(256)) != '':
108+ process(block)
109+
110+ Another motivating use case arises in list comprehensions where
111+ a value computed in a filtering condition is also needed in
112+ the expression body::
113+
114+ [clean_name.title() for name in names
115+ if (clean_name := normalize('NFC', name)) in allowed_names]
116+
117+ Try to limit use of the walrus operator to clean cases that reduce
118+ complexity and improve readability.
119+
85120See:pep: `572 ` for a full description.
86121
87122(Contributed by Emily Morehouse in:issue: `35224 `.)
@@ -92,20 +127,69 @@ See :pep:`572` for a full description.
92127 Positional-only parameters
93128--------------------------
94129
95- There is new syntax (``/ ``) to indicate that some function parameters
96- must be specified positionally (i.e., cannot be used as keyword
97- arguments). This is the same notation as shown by ``help() `` for
98- functions implemented in C (produced by Larry Hastings' "Argument
99- Clinic" tool). Example::
130+ There is a new function parameter syntax ``/ `` to indicate that some
131+ function parameters must be specified positionally and cannot be used as
132+ keyword arguments. This is the same notation shown by ``help() `` for C
133+ functions annotated with Larry Hastings' `Argument Clinic
134+ <https://docs.python.org/3/howto/clinic.html> `_ tool.
135+
136+ In the following example, parameters *a * and *b * are positional-only,
137+ while *c * or *d * can be positional or keyword, and *e * or *f * are
138+ required to be keywords::
139+
140+ def f(a, b, /, c, d, *, e, f):
141+ print(a, b, c, d, e, f)
142+
143+ The following is a valid call::
144+
145+ f(10, 20, 30, d=40, e=50, f=60)
146+
147+ However, these are invalid calls::
148+
149+ f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument
150+ f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument
151+
152+ One use case for this notation is that it allows pure Python functions
153+ to fully emulate behaviors of existing C coded functions. For example,
154+ the built-in:func: `pow ` function does not accept keyword arguments::
100155
101156 def pow(x, y, z=None, /):
102- r = x**y
103- if z is not None:
104- r %= z
105- return r
157+ "Emulate the built in pow() function"
158+ r = x ** y
159+ return r if z is None else r%z
160+
161+ Another use case is to preclude keyword arguments when the parameter
162+ name is not helpful. For example, the builtin:func: `len ` function has
163+ the signature ``len(obj, /) ``. This precludes awkward calls such as::
106164
107- Now ``pow(2, 10) `` and ``pow(2, 10, 17) `` are valid calls, but
108- ``pow(x=2, y=10) `` and ``pow(2, 10, z=17) `` are invalid.
165+ len(obj='hello') # The "obj" keyword argument impairs readability
166+
167+ A further benefit of marking a parameter as positional-only is that it
168+ allows the parameter name to be changed in the future without risk of
169+ breaking client code. For example, in the:mod: `statistics ` module, the
170+ parameter name *dist * may be changed in the future. This was made
171+ possible with the following function specification::
172+
173+ def quantiles(dist, /, *, n=4, method='exclusive')
174+ ...
175+
176+ Since the parameters to the left of ``/ `` are not exposed as possible
177+ keywords, the parameters names remain available for use in ``**kwargs ``::
178+
179+ >>> def f(a, b, /, **kwargs):
180+ ... print(a, b, kwargs)
181+ ...
182+ >>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways
183+ 10 20 {'a': 1, 'b': 2, 'c': 3}
184+
185+ This greatly simplifies the implementation of functions and methods
186+ that need to accept arbitrary keyword arguments. For example, here
187+ is an except from code in the:mod: `collections ` module::
188+
189+ class Counter(dict):
190+
191+ def __init__(self, iterable=None, /, **kwds):
192+ # Note "iterable" is a possible keyword argument
109193
110194See:pep: `570 ` for a full description.
111195
@@ -174,17 +258,31 @@ Android and Cygwin, whose cases are handled by the script);
174258this change is backward incompatible on purpose.
175259(Contributed by Victor Stinner in:issue: `36721 `.)
176260
177- f-strings now support = for quick and easy debugging
178- -----------------------------------------------------
179261
180- Add ``= `` specifier to f-strings. ``f'{expr=}' `` expands
181- to the text of the expression, an equal sign, then the repr of the
182- evaluated expression. So::
262+ f-strings support ``= `` for self-documenting expressions and debugging
263+ ----------------------------------------------------------------------
264+
265+ Added an ``= `` specifier to:term: `f-string `\s . An f-string such as
266+ ``f'{expr=}' `` will expand to the text of the expression, an equal sign,
267+ then the representation of the evaluated expression. For example:
183268
184- x = 3
185- print(f'{x*9 + 15=}')
269+ >>>user= ' eric_idle'
270+ >>>member_since= date(1975 ,7 ,31 )
271+ >>>f ' { user= } { member_since= } '
272+ "user='eric_idle' member_since=datetime.date(1975, 7, 31)"
186273
187- Would print ``x*9 + 15=42 ``.
274+ The usual:ref: `f-string format specifiers <f-strings >` allow more
275+ control over how the result of the expression is displayed::
276+
277+ >>> delta = date.today() - member_since
278+ >>> f'{user=!s} {delta.days=:,d}'
279+ 'user=eric_idle delta.days=16,075'
280+
281+ The ``= `` specifier will display the whole expression so that
282+ calculations can be shown::
283+
284+ >>> print(f'{theta=} {cos(radians(theta))=:.3f}')
285+ theta=30 cos(radians(theta))=0.866
188286
189287(Contributed by Eric V. Smith and Larry Hastings in:issue: `36817 `.)
190288
@@ -295,7 +393,13 @@ Other Language Changes
295393 or:meth: `~object.__complex__ ` is not available.
296394 (Contributed by Serhiy Storchaka in:issue: `20092 `.)
297395
298- * Added support of ``\N{name} `` escapes in:mod: `regular expressions <re> `.
396+ * Added support of ``\N{name} `` escapes in:mod: `regular expressions <re> `::
397+
398+ >>> notice = 'Copyright © 2019'
399+ >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})')
400+ >>> int(copyright_year_pattern.search(notice).group(1))
401+ 2019
402+
299403 (Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
300404
301405* Dict and dictviews are now iterable in reversed insertion order using
@@ -343,10 +447,30 @@ Other Language Changes
343447* Added new ``replace() `` method to the code type (:class: `types.CodeType `).
344448 (Contributed by Victor Stinner in:issue: `37032 `.)
345449
346- * For integers, the three-argument form of the:func: `pow ` function now permits
347- the exponent to be negative in the case where the base is relatively prime to
348- the modulus. It then computes a modular inverse to the base when the exponent
349- is ``-1 ``, and a suitable power of that inverse for other negative exponents.
450+ * For integers, the three-argument form of the:func: `pow ` function now
451+ permits the exponent to be negative in the case where the base is
452+ relatively prime to the modulus. It then computes a modular inverse to
453+ the base when the exponent is ``-1 ``, and a suitable power of that
454+ inverse for other negative exponents. For example, to compute the
455+ `modular multiplicative inverse
456+ <https://en.wikipedia.org/wiki/Modular_multiplicative_inverse> `_ of 38
457+ modulo 137, write::
458+
459+ >>> pow(38, -1, 137)
460+ 119
461+ >>> 119 * 38 % 137
462+ 1
463+
464+ Modular inverses arise in the solution of `linear Diophantine
465+ equations <https://en.wikipedia.org/wiki/Diophantine_equation> `_.
466+ For example, to find integer solutions for ``4258𝑥 + 147𝑦 = 369 ``,
467+ first rewrite as ``4258𝑥 ≡ 369 (mod 147) `` then solve:
468+
469+ >>>x= 369 * pow (4258 ,- 1 ,147 )% 147
470+ >>>y= (4258 * x- 369 )// - 147
471+ >>>4258 * x+ 147 * y
472+ 369
473+
350474 (Contributed by Mark Dickinson in:issue: `36027 `.)
351475
352476* When dictionary comprehensions are evaluated, the key is now evaluated before
@@ -573,7 +697,14 @@ Formerly, it only supported the 2-D case.
573697
574698Added new function,:func: `math.prod `, as analogous function to:func: `sum `
575699that returns the product of a 'start' value (default: 1) times an iterable of
576- numbers. (Contributed by Pablo Galindo in:issue: `35606 `)
700+ numbers::
701+
702+ >>> prior = 0.8
703+ >>> likelihoods = [0.625, 0.84, 0.30]
704+ >>> (link: http://math.prod) math.prod(likelihoods, start=prior)
705+ 0.126
706+
707+ (Contributed by Pablo Galindo in:issue: `35606 `)
577708
578709Added new function:func: `math.isqrt ` for computing integer square roots.
579710(Contributed by Mark Dickinson in:issue: `36887 `.)
@@ -1354,7 +1485,7 @@ Changes in the Python API
13541485*:func: `shutil.copyfile ` default buffer size on Windows was changed from
13551486 16 KiB to 1 MiB.
13561487
1357- * ``PyGC_Head `` structis changed completely. All code touched the
1488+ *The ``PyGC_Head `` structhas changed completely. All code that touched the
13581489 struct member should be rewritten. (See:issue: `33597 `)
13591490
13601491* The ``PyInterpreterState `` struct has been moved into the "internal"