Skip to content

Commit 4f9ffc9

Browse files
authored
bpo-37759: First round of major edits to Whatsnew 3.8 (GH-15127)
1 parent 1213123 commit 4f9ffc9

2 files changed

Lines changed: 169 additions & 37 deletions

File tree

‎Doc/whatsnew/3.8.rst‎

Lines changed: 168 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,25 @@
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.
4748
For 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

6266
Summary -- Release highlights
@@ -76,12 +80,43 @@ New Features
7680
Assignment 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+
85120
See :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

110194
See :pep:`570` for a full description.
111195

@@ -174,17 +258,31 @@ Android and Cygwin, whose cases are handled by the script);
174258
this 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
@@ -576,7 +700,14 @@ Formerly, it only supported the 2-D case.
576700

577701
Added new function, :func:`math.prod`, as analogous function to :func:`sum`
578702
that returns the product of a 'start' value (default: 1) times an iterable of
579-
numbers. (Contributed by Pablo Galindo in :issue:`35606`)
703+
numbers::
704+
705+
>>> prior = 0.8
706+
>>> likelihoods = [0.625, 0.84, 0.30]
707+
>>> (link: http://math.prod) math.prod(likelihoods, start=prior)
708+
0.126
709+
710+
(Contributed by Pablo Galindo in :issue:`35606`)
580711

581712
Added new function :func:`math.isqrt` for computing integer square roots.
582713
(Contributed by Mark Dickinson in :issue:`36887`.)
@@ -1357,7 +1488,7 @@ Changes in the Python API
13571488
* :func:`shutil.copyfile` default buffer size on Windows was changed from
13581489
16 KiB to 1 MiB.
13591490

1360-
* ``PyGC_Head`` struct is changed completely. All code touched the
1491+
* The ``PyGC_Head`` struct has changed completely. All code that touched the
13611492
struct member should be rewritten. (See :issue:`33597`)
13621493

13631494
* The ``PyInterpreterState`` struct has been moved into the "internal"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Beginning edits to Whatsnew 3.8

0 commit comments

Comments
 (0)