Python 3.6 有什麼新功能¶
- 編輯者:
Elvis Pranskevichus <elvis@magic.io>, Yury Selivanov <yury@magic.io>
本文介紹了 Python 3.6 與 3.5 相比多了哪些新功能。Python 3.6 已於 2016 年 12 月 23 日發布。完整詳情請見 changelog。
也參考
PEP 494 - Python 3.6 發佈時程
發布重點摘要¶
新增語法特性:
PEP 498, formatted string literals.
PEP 515, underscores in numeric literals.
PEP 526, syntax for variable annotations.
PEP 525, asynchronous generators.
PEP 530: asynchronous comprehensions.
新的函式庫模組:
CPython 實作改進:
The dict type has been reimplemented to use a more compact representation based on a proposal by Raymond Hettinger and similar to the PyPy dict implementation. This resulted in dictionaries using 20% to 25% less memory when compared to Python 3.5.
Customization of class creation has been simplified with the new protocol.
The class attribute definition order is now preserved.
The order of elements in
**kwargsnow corresponds to the order in which keyword arguments were passed to the function.DTrace and SystemTap probing support has been added.
The new PYTHONMALLOC environment variable can now be used to debug the interpreter memory allocation and access errors.
標準函式庫中的顯著改進
The
asynciomodule has received new features, significant usability and performance improvements, and a fair amount of bug fixes. Starting with Python 3.6 theasynciomodule is no longer provisional and its API is considered stable.A new file system path protocol has been implemented to support path-like objects. All standard library functions operating on paths have been updated to work with the new protocol.
The
datetimemodule has gained support for Local Time Disambiguation.The
typingmodule received a number of improvements.The
tracemallocmodule has been significantly reworked and is now used to provide better output forResourceWarningas well as provide better diagnostics for memory allocation errors. See the PYTHONMALLOC section for more information.
安全性改進:
The new
secretsmodule has been added to simplify the generation of cryptographically strong pseudo-random numbers suitable for managing secrets such as account authentication, tokens, and similar.On Linux,
os.urandom()now blocks until the system urandom entropy pool is initialized to increase the security. See the PEP 524 for the rationale.The default settings and feature set of the
sslmodule have been improved.The
hashlibmodule received support for the BLAKE2, SHA-3 and SHAKE hash algorithms and thescrypt()key derivation function.
Windows 改進:
PEP 528 and PEP 529, Windows filesystem and console encoding changed to UTF-8.
The
py.exelauncher, when used interactively, no longer prefers Python 2 over Python 3 when the user doesn't specify a version (via command line arguments or a config file). Handling of shebang lines remains unchanged - "python" refers to Python 2 in that case.python.exeandpythonw.exehave been marked as long-path aware, which means that the 260 character path limit may no longer apply. See removing the MAX_PATH limitation for details.A
._pthfile can be added to force isolated mode and fully specify all search paths to avoid registry and environment lookup. See the documentation for more information.A
python36.zipfile now works as a landmark to inferPYTHONHOME. See the documentation for more information.
新增功能¶
PEP 498: Formatted string literals¶
PEP 498 introduces a new kind of string literals: f-strings, or formatted string literals.
Formatted string literals are prefixed with 'f' and are similar to
the format strings accepted by str.format(). They contain replacement
fields surrounded by curly braces. The replacement fields are expressions,
which are evaluated at run time, and then formatted using the
format() protocol:
>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}" # 巢狀欄位
'result: 12.35'
PEP 526: Syntax for variable annotations¶
PEP 484 introduced the standard for type annotations of function parameters, a.k.a. type hints. This PEP adds syntax to Python for annotating the types of variables including class variables and instance variables:
primes: List[int] = []
captain: str # Note: no initial value!
class Starship:
stats: Dict[str, int] = {}
Just as for function annotations, the Python interpreter does not attach any
particular meaning to variable annotations and only stores them in the
__annotations__ attribute of a class or module.
In contrast to variable declarations in statically typed languages,
the goal of annotation syntax is to provide an easy way to specify structured
type metadata for third party tools and libraries via the abstract syntax tree
and the __annotations__ attribute.
PEP 515: Underscores in Numeric Literals¶
PEP 515 adds the ability to use underscores in numeric literals for improved readability. For example:
>>> 1_000_000_000_000_000
1000000000000000
>>> 0x_FF_FF_FF_FF
4294967295
Single underscores are allowed between digits and after any base specifier. Leading, trailing, or multiple underscores in a row are not allowed.
The string formatting language also now has support
for the '_' option to signal the use of an underscore for a thousands
separator for floating-point presentation types and for integer
presentation type 'd'. For integer presentation types 'b',
'o', 'x', and 'X', underscores will be inserted every 4
digits:
>>> '{:_}'.format(1000000)
'1_000_000'
>>> '{:_x}'.format(0xFFFFFFFF)
'ffff_ffff'
也參考
- PEP 515 -- Underscores in Numeric Literals
由 Georg Brandl 與 Serhiy Storchaka 撰寫 PEP。
PEP 525: Asynchronous Generators¶
PEP 492 introduced support for native coroutines and async / await
syntax to Python 3.5. A notable limitation of the Python 3.5 implementation
is that it was not possible to use await and yield in the same
function body. In Python 3.6 this restriction has been lifted, making it
possible to define asynchronous generators:
async def ticker(delay, to):
"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
yield i
await asyncio.sleep(delay)
The new syntax allows for faster and more concise code.
也參考
- PEP 525 -- Asynchronous Generators
由 Yury Selivanov 撰寫 PEP 與實作。
PEP 530: Asynchronous Comprehensions¶
PEP 530 adds support for using async for in list, set, dict
comprehensions and generator expressions:
result = [i async for i in aiter() if i % 2]
Additionally, await expressions are supported in all kinds
of comprehensions:
result = [await fun() for fun in funcs if await condition()]
也參考
- PEP 530 -- Asynchronous Comprehensions
由 Yury Selivanov 撰寫 PEP 與實作。
PEP 487: Simpler customization of class creation¶
It is now possible to customize subclass creation without using a metaclass.
The new __init_subclass__ classmethod will be called on the base class
whenever a new subclass is created:
class PluginBase:
subclasses = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.subclasses.append(cls)
class Plugin1(PluginBase):
pass
class Plugin2(PluginBase):
pass
In order to allow zero-argument super() calls to work correctly from
__init_subclass__() implementations, custom metaclasses must
ensure that the new __classcell__ namespace entry is propagated to
type.__new__ (as described in Creating the class object).
也參考
- PEP 487 -- Simpler customization of class creation
由 Martin Teichmann 撰寫 PEP 與實作。
PEP 487: Descriptor Protocol Enhancements¶
PEP 487 extends the descriptor protocol to include the new optional
__set_name__() method. Whenever a new class is defined, the new
method will be called on all descriptors included in the definition, providing
them with a reference to the class being defined and the name given to the
descriptor within the class namespace. In other words, instances of
descriptors can now know the attribute name of the descriptor in the
owner class:
class IntField:
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, int):
raise ValueError(f'expecting integer in {self.name}')
instance.__dict__[self.name] = value
# this is the new initializer:
def __set_name__(self, owner, name):
self.name = name
class Model:
int_field = IntField()
也參考
- PEP 487 -- Simpler customization of class creation
由 Martin Teichmann 撰寫 PEP 與實作。
PEP 519: Adding a file system path protocol¶
File system paths have historically been represented as str
or bytes objects. This has led to people who write code which
operate on file system paths to assume that such objects are only one
of those two types (an int representing a file descriptor
does not count as that is not a file path). Unfortunately that
assumption prevents alternative object representations of file system
paths like pathlib from working with pre-existing code,
including Python's standard library.
To fix this situation, a new interface represented by
os.PathLike has been defined. By implementing the
__fspath__() method, an object signals that it
represents a path. An object can then provide a low-level
representation of a file system path as a str or
bytes object. This means an object is considered
path-like if it implements
os.PathLike or is a str or bytes object
which represents a file system path. Code can use os.fspath(),
os.fsdecode(), or os.fsencode() to explicitly get a
str and/or bytes representation of a path-like
object.
The built-in open() function has been updated to accept
os.PathLike objects, as have all relevant functions in the
os and os.path modules, and most other functions and
classes in the standard library. The os.DirEntry class
and relevant classes in pathlib have also been updated to
implement os.PathLike.
The hope is that updating the fundamental functions for operating
on file system paths will lead to third-party code to implicitly
support all path-like objects without any
code changes, or at least very minimal ones (e.g. calling
os.fspath() at the beginning of code before operating on a
path-like object).
Here are some examples of how the new interface allows for
pathlib.Path to be used more easily and transparently with
pre-existing code:
>>> import pathlib
>>> with open(pathlib.Path("README")) as f:
... contents = f.read()
...
>>> import os.path
>>> os.path.splitext(pathlib.Path("some_file.txt"))
('some_file', '.txt')
>>> os.path.join("/a/b", pathlib.Path("c"))
'/a/b/c'
>>> import os
>>> os.fspath