Python 3.8 有什麼新功能¶
- 編輯者:
Raymond Hettinger
本文介紹了 Python 3.8 與 3.7 相比多了哪些新功能。Python 3.8 已於 2019 年 10 月 14 日發布。有關完整詳細資訊,請參閱 changelog。
發布重點摘要¶
新增功能¶
Assignment expressions¶
There is new syntax := that assigns values to variables as part of a larger
expression. It is affectionately known as "the walrus operator" due to
its resemblance to the eyes and tusks of a walrus.
In this example, the assignment expression helps avoid calling
len() twice:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
A similar benefit arises during regular expression matching where match objects are needed twice, once to test whether a match occurred and another to extract a subgroup:
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
The operator is also useful with while-loops that compute a value to test loop termination and then need that same value again in the body of the loop:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
Another motivating use case arises in list comprehensions where a value computed in a filtering condition is also needed in the expression body:
[clean_name.title() for name in names
if (clean_name := normalize('NFC', name)) in allowed_names]
Try to limit use of the walrus operator to clean cases that reduce complexity and improve readability.
完整敘述請見 PEP 572。
(由 Emily Morehouse 在 bpo-35224 中貢獻。)
Positional-only parameters¶
There is a new function parameter syntax / to indicate that some
function parameters must be specified positionally and cannot be used as
keyword arguments. This is the same notation shown by help() for C
functions annotated with Larry Hastings'
Argument Clinic tool.
In the following example, parameters a and b are positional-only, while c or d can be positional or keyword, and e or f are required to be keywords:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
以下是有效的呼叫:
f(10, 20, 30, d=40, e=50, f=60)
然而以下這些呼叫是無效的:
f(10, b=20, c=30, d=40, e=50, f=60) # b 不得為關鍵字引數
f(10, 20, 30, 40, 50, f=60) # e 必須為關鍵字引數
One use case for this notation is that it allows pure Python functions
to fully emulate behaviors of existing C coded functions. For example,
the built-in divmod() function does not accept keyword arguments:
def divmod(a, b, /):
"Emulate the built in divmod() function"
return (a // b, a % b)
Another use case is to preclude keyword arguments when the parameter
name is not helpful. For example, the builtin len() function has
the signature len(obj, /). This precludes awkward calls such as:
len(obj='hello') # The "obj" keyword argument impairs readability
A further benefit of marking a parameter as positional-only is that it
allows the parameter name to be changed in the future without risk of
breaking client code. For example, in the statistics module, the
parameter name dist may be changed in the future. This was made
possible with the following function specification:
def quantiles(dist, /, *, n=4, method='exclusive')
...
Since the parameters to the left of / are not exposed as possible
keywords, the parameters names remain available for use in **kwargs:
>>> def f(a, b, /, **kwargs):
... print(a, b, kwargs)
...
>>> f(10, 20, a=1, b=2, c=3) # a 和 b 被用於兩種方式
10 20 {'a': 1, 'b': 2, 'c': 3}
This greatly simplifies the implementation of functions and methods
that need to accept arbitrary keyword arguments. For example, here
is an excerpt from code in the collections module:
class Counter(dict):
def __init__(self, iterable=None, /, **kwds):
# Note "iterable" is a possible keyword argument
完整敘述請見 PEP 570。
(由 Pablo Galindo 在 bpo-36540 中貢獻。)
Parallel filesystem cache for compiled bytecode files¶
The new PYTHONPYCACHEPREFIX setting (also available as
-X pycache_prefix) configures the implicit bytecode
cache to use a separate parallel filesystem tree, rather than
the default __pycache__ subdirectories within each source
directory.
The location of the cache is reported in sys.pycache_prefix
(None indicates the default location in __pycache__
subdirectories).
(由 Carl Meyer 在 bpo-33499 中貢獻。)
Debug build uses the same ABI as release build¶
The ABI of Python debug builds is now compatible with Python release builds. On Unix, when Python is built in debug mode, it is now possible to load C extensions built in release mode and C extensions built using the stable ABI. The inverse is not true, as debug builds expose additional symbols not available in release builds.
Defining the Py_DEBUG macro no longer implies the Py_TRACE_REFS macro,
which introduces the only ABI incompatibility. The Py_TRACE_REFS macro,
which adds the sys.getobjects() function and the PYTHONDUMPREFS
environment variable, can be set using the new ./configure
--with-trace-refs build option.
(Contributed by Victor Stinner in bpo-36465.)
On Unix, C extensions are no longer linked to libpython except on Android and Cygwin. It is now possible for a statically linked Python to load a C extension built using a shared library Python. (Contributed by Victor Stinner in bpo-21536.)
On Unix, when Python is built in debug mode, import now also looks for C extensions compiled in release mode and for C extensions compiled with the stable ABI. (Contributed by Victor Stinner in bpo-36722.)
To embed Python into an application, a new --embed option must be passed to
python3-config --libs --embed to get -lpython3.8 (link the application
to libpython). To support both 3.8 and older, try python3-config --libs
--embed first and fallback to python3-config --libs (without --embed)
if the previous command fails.
Add a pkg-config python-3.8-embed module to embed Python into an
application: pkg-config python-3.8-embed --libs includes -lpython3.8.
To support both 3.8 and older, try pkg-config python-X.Y-embed --libs first
and fallback to pkg-config python-X.Y --libs (without --embed) if the
previous command fails (replace X.Y with the Python version).
On the other hand, pkg-config python3.8 --libs no longer contains
-lpython3.8. C extensions must not be linked to libpython (except on
Android and Cygwin, whose cases are handled by the script);
this change is backward incompatible on purpose.
(Contributed by Victor Stinner in bpo-36721.)
f-strings support = for self-documenting expressions and debugging¶
Added an = specifier to f-strings. An f-string such as
f'{expr=}' will expand to the text of the expression, an equal sign,
then the representation of the evaluated expression. For example:
>>> import datetime as dt
>>> user = 'eric_idle'
>>> member_since = dt.date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
The usual f-string format specifiers allow more control over how the result of the expression is displayed:
>>> delta = dt.date.today() - member_since
>>> f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,075'
The = specifier will display the whole expression so that
calculations can be shown:
>>> print(f'{theta=} {cos(radians(theta))=:.3f}')
theta=30 cos(radians(theta))=0.866
(由 Eric V. Smith 和 Larry Hastings 在 bpo-36817 中貢獻。)
PEP 578: Python Runtime Audit Hooks¶
The PEP adds an Audit Hook and Verified Open Hook. Both are available from Python and native code, allowing applications and frameworks written in pure Python code to take advantage of extra notifications, while also allowing embedders or system administrators to deploy builds of Python where auditing is always enabled.
完整細節請見 PEP 578。
PEP 587: Python Initialization Configuration¶
The PEP 587 adds a new C API to configure the Python Initialization providing finer control on the whole configuration and better error reporting.
New structures: