昨天,Python发布了 [3.7a4](Python Release Python 3.7.0a4),按照官方发布计划,月底Python 3.7 将迎来第一个 beta 版本,不再有新功能的添加,那么让我们看一下,Python 3.7到底有什么改进呢?
新增功能
新版本中共新增了9个 PEP 标准,并没有特别惊艳的改变,下面主要介绍一些语法和写法上的新变化。
PEP-553 内置断点支持
以前使用pdb的时候,需要import pdb然后pdb.set_trace(),现在使用内置的breakpoint()函数可以快速中断。同时,breakpoint()可以使用任意的调试工具,这也方便了在调试代码时的扩展。你可以通过PYTHONBREAKPOINT=0环境变量禁用这个功能。
PEP-562 限制访问模块的属性
我们之前在编写Python模块时,通常无法限制使用者使用内部的属性,比较典型的例子是在管理失效警告时。新的语法通过对模块添加__getattr__和__dir__,可以实现限制访问/提醒失效目的。
举一个例子,假如需要失效部分方法时,我们需要在使用之前进行提醒:
# lib.py
from warnings import warn
deprecated_names = ["old_function", ...]
def _deprecated_old_function(arg, other):
...
def __getattr__(name):
if name in deprecated_names:
warn(f"{name}is deprecated", DeprecationWarning)
return globals()[f"_deprecated_{name}"]
raise AttributeError(f"module{__name__}has no attribute{name}")
# main.py
from lib import old_function # Works, but emits the warning
同样的__dir__也可以用在类似的用途上:
# lib.py
deprecated_names = ["old_function", ...]
__all__ = ["new_function_one", "new_function_two", ...]
def new_function_one(arg, other):
...
def new_function_two(arg, other):
...
def __dir__():
return sorted(__all__ + deprecated_names)
# main.py
import lib
dir(lib) # prints ["new_function_one", "new_function_two", "old_function", ...]
PEP-564 支持nanosecond的时间函数
方便对nanosecond的操作,提供了6个新增的函数,分别为clock_gettime_ns(), clock_settime_ns(),monotonic_ns(),perf_counter_ns(),process_time_ns()和time_ns()。基本上是在原有函数的基础上添加_ns结尾标记,用法也基本相同。
PEP-557 数据类装饰器
在新版本中添加了@dataclass装饰器,利用该装饰器可以减少数据类型定义的代码行数。比如我们有一个类用于存储数据:
@dataclass
class InventoryItem:
'''Class for keeping track of an item in inventory.'''
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_han
使用之后,则相当于添加了以下类方法:
def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0) -> None:
self.name = name
self.unit_price = unit_price
self.quantity_on_hand = quantity_on_hand
def __repr__(self):
return f'InventoryItem(name={self.name!r}, unit_price={self.unit_price!r}, quantity_on_hand={self.quantity_on_hand!r})'
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) == (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __ne__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) != (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) < (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __le__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) <= (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __gt__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) > (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __ge__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) >= (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
你可以通过@dataclass(init=True, repr=True, eq=True, order=False, hash=None, frozen=False)这种形式启用和禁用部分实现。
其他
其他的内容,PEP-538 和 PEP-540 均是关于 Python对于UTF-8环境的支持,其中538主要影响了 *nix 系统下的UTF-8字符串显示,PEP-540主要是扩大了默认UTF-8编码的范围,比如sys.getfilesystemencoding()等将会返回UTF-8。这些问题一般用户并不会遇到,因此我这里不做更多描述,有兴趣的可以去看下具体的内容即可。PEP-552扩展了pyc文件的格式,更好的支持pyc缓存,感觉作用不大,这里也不做太多介绍。PEP-539定义了一套新的Thread Soecific Storage API,提升对跨平台的支持性,这里也不做介绍了。
性能改进
部分Python3性能都进行了提升,不过都不如关于函数调用的改进最为明显。通过添加LOAD_METHOD和CALL_METHOD两个opcode,函数调用进行了较大提升。基本上对于2.7版本而言,大部分的性能已经超过,只有少数指标仍旧落后于Python2.7。
更多详情
更多的详情可以在 Python 官方网站中查询更多信息。