我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python 3.7 新特性概览(附实例

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python 3.7 新特性概览(附实例

译自:https://hackaday.com/2018/07/23/hands-on-with-python-3-7-whats-new-in-the-latest-release/?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

目录

内置 breakpoint()

注解和类型

计时

Dataclass

其他

结论


许多人使用的第一种、被称为世界上增长最快的编程语言当然是 Python,可用于通用编程、数据科学、网站后端、GUI 以及几乎所有其他功能。最新的 3.7.0 版本 刚发布不久。

任何版本 Python 的发行,无论变化多小,在任何开发开始之前都要经过细致的规划和设计。实际上,你可以阅读 Python 3.7 的PEP (Python Enhancement Proposal,Python 增强提议),该提议是在2016年创建的。

3.7 中有什么新功能?你为什么要升级?有什么新的有用的东西吗?我将通过介绍一些新特性的例子来回答这些问题。虽然这个版本对 Python 初学者来说没有什么不同,但是对于经验丰富的程序员来说有很多小的变化,还有一些你想要了解的主要特性。


任何使用过 pdb (Python debugger) 的人都知道它有多么强大。它能暂停脚本的执行,允许你在程序的内部手动浏览,并且单步执行语句。

但是,到目前为止,在编写程序时需要进行一些设置。当然,导入 pdb 和 set_trace() 几乎不需要花费任何时间,但这不如插入快速调试 print() 或 log 方便。在 Python 3.7 中,breakpoint() 是内置函数,可以非常容易地在任何时候插入调试器。同样值得注意的是,pdb 只是众多可用调试器之一,你可以通过设置新的 PYTHONBREAKPOINT 环境变量来配置想要使用的调试器。

这里有一个简单例子。用户需要输入一个字符串,判断它是否匹配一个值。


"""Test user's favourite Integrated Circuit."""
 
def test_ic(favourite_ic):
    user_guess = input("Try to guess our favourite IC >>> ")
 
    if user_guess == favourite_ic:
        return "Yup, that's our favourite!"
    else:
        return "Sorry, that's not our favourite IC"
 
 
if __name__ == '__main__':
    favourite_ic = 555
    print(test_ic(favourite_ic))

不幸的是,无论输入什么,我们都无法匹配字符串。


$ python breakpoint_test.py
Try to guess our favourite IC >>> 555
Sorry, that's not our favourite IC

为了弄清楚发生了什么,让我们插入一个断点 —— 只需要调用 breakpoint()


"""Test user's favourite Integrated Circuit."""
 
def test_ic(favourite_ic):
    user_guess = input("Try to guess our favourite IC >>> ")
    breakpoint()
 
    if user_guess == favourite_ic:
        return "Yup, that's our favourite!"
    else:
        return "Sorry, that's not our favourite IC"
 
 
if __name__ == '__main__':
    favourite_ic = 555
    print(test_ic(favourite_ic))

在 pdb 提示符下,我们将调用 locals() 来调出当前的本地作用域。pdb 有大量有用的命令,但是你也可以在其中运行正常的Python 语句。


$ python breakpoint_test.py
Try to guess our favourite IC >>> 555
> /home/ben/Hackaday/python37/breakpoint_test.py(8)test_ic()
-> if user_guess == favourite_ic:
(Pdb) locals()
{'favourite_ic': 555, 'user_guess': '555'}
(Pdb)

啊哈!看起来 favourite_ic 是一个整数,而 user_guess 是一个字符串。因为在 Python 中,将字符串与 int 进行比较是完全可行的,所以没有抛出异常(但是比较没有达到我们想要的效果)。favourite_ic 应该声明为字符串,这可以说是 Python 的动态类型的危险之一 —— 在运行时之前无法捕捉到这个错误。当然,除非你使用类型注解……


从 Python 3.5 开始,类型注解就越来越受欢迎。对于那些不熟悉类型提示的人来说,这是一种完全可选的注释代码的方式,以指定变量的类型。

类型提示(Type hints)只是 annotations 的一个应用。注解是什么?它们是关联元数据与变量的语法支持,可以是任意表达式,在运行时被 Python 计算但被忽略。注解可以是任何有效的 Python 表达式。这里有一个带注解的函数的例子,但这个例子中使用了一些无用的信息。


# Without annotation
def foo(bar, baz):
# Annotated
def foo(bar: 'Describe the bar', baz: print('random')) -> 'return thingy':

这一切都很酷,但有点无意义,除非以标准方式使用注解。在 Python 3.5 (PEP 484)中,使用注解进行编程的语法变得标准化,此后,Python 社区广泛使用了类型提示。它们纯粹是一种开发工具,可以使用 PyCharm 等 IDE 或 Mypy 等第三方工具进行检查。

如果我们的字符串比较程序是用类型注解编写的,它应该是这样的:


"""Test user's favourite Integrated Circuit."""
 
def test_ic(favourite_ic: str) -> str:
    user_guess: str = input("Try to guess our favourite IC >>> ")
    breakpoint()
 
    if user_guess == favourite_ic:
        return "Yup, that's our favourite!"
    else:
        return "Sorry, that's not our favourite IC"
 
 
if __name__ == '__main__':
    favourite_ic: int = 555
    print(test_ic(favourite_ic))

你可以看到 PyCharm 提醒了我这个错误,它可以防止我在运行时才注意到它。

这就是注解和类型提示的基础。Python 3.7 中有什么变化?正如官方的 Python 文档所指出的,当人们开始使用注解作为类型提示时,出现了两个主要问题:启动性能和前向引用。

  • 不出意外的是,在定义时计算大量任意表达式相当影响启动性能,而且 typing 模块非常慢
  • 你不能用尚未声明的类型来注解

这种缺乏前向引用的做法似乎是合理的,但在实践中却变得相当麻烦。


class User:
    def __init__(self, name: str, prev_user: User) -> None:
        pass

这种做法将失败,因为 User 还没有被声明,因此 prev_user 不能定义为 User 类型。

为了解决这两个问题,注解的评估被推迟。

要实现上述行为,必须导入 __future__,因为在保持与以前版本兼容的情况下无法进行此更改。


from __future__ import annotations
 
class User: 
    def __init__(self, name: str, prev_user: User) -> None:
        pass

typing 模块如此缓慢的部分原因是,最初的设计目标是在不修改核心 CPython 解释器的情况下实现 typing 模块。既然类型提示变得越来越流行,这一限制已经被移除,这意味着现在有了对 typing 的核心支持,使得支持多种优化


time 模块在定时上加入了一些新功能:现有的定时器功能达到了纳秒级,这意味着如果需要的话,可以有更高的精度。一些基准测试表明,time.time() 的分辨率是 time.time_ns() 的三倍以上。

说到时间,Python 本身在 3.7 中获得了一个小的速度提升。这是底层的内容,所以我们现在不深入讨论,这里有完整的优化列表。你只需要知道,在 Linux 上的启动时间比之前要快 10%,在 MacOS 上快 30%,大量的方法调用要快 20%。


我敢打赌,如果你曾经编写过面向对象的 Python,你就会创建一个类,最终看起来像这样:


class User:
 
    def __init__(self, name: str, age: int, favourite_ic: str) -> None:
        self.name = name
        self.age = age
        self.favourite_ic = favourite_ic
 
    def is_adult(self) -> bool:
        """Return True if user is an adult, else False."""
        return self.age >= 18
 
 
if __name__ == '__main__':
    john = User('John', 29, '555')
    print(john)
    # prints "<__main__.User object at 0x0076E610>"

当类被初始化时,__init__ 会接收到大量不同的参数。这些属性直接设置为类实例的属性,供以后使用。在编写这类类时,这是一种非常常见的模式 —— 但这是Python,如果可以避免单调乏味,那么它就可以。

在 3.7 中,我们有 dataclass,这将使这类类更容易声明,也更可读。

只需用 @dataclass 装饰类,self 的赋值就会自动处理。变量的声明如下所示,类型注解是强制性的(如果你想灵活的话,你仍然可以使用 Any 类型)。


from dataclasses import dataclass
 
@dataclass
class User:
    name: str
    age: int
    favourite_ic: str
 
    def is_adult(self) -> bool:
        """Return True if user is an adult, else False."""
        return self.age >= 18
 
if __name__ == '__main__': 
    john = User('John', 29, '555') 
    print(john) 
    # prints "User(name='John', age=29, favourite_ic='555')"

这使得类不仅容易设置,而且当我们创建一个实例并打印出来时,它还生成了一个优美的字符串。在与其他类实例进行比较时,它也会有适当的行为。这是因为,除了自动生成 __init__ 方法外,还生成了其他特殊方法,如 __repr____eq____hash__ 等。当定义这样的类时,大大减少了所需的开销。

Dataclass 使用字段 (field) 来完成它们的工作,手动构造一个 field() 函数能够访问其他选项,从而更改默认值。例如,这里将 field 中的 default_factory 设置为一个 lambda 函数,该函数提示用户输入其名称。


from dataclasses import dataclass, field
 
class User:
    name: str = field(default_factory=lambda: input("enter name"))

(我们不建议直接将 input 输入到属性中,这只是一个字段功能的演示。)


在这个版本中还有许多其他的变化;我们将在这里列出一些最重要的:

  • 字典现在保持插入顺序。这在 3.6 中是非正式的,但现在是官方语言规范。在大多数情况下,普通的 dict 应该能够替换 collections.OrderedDict
  • 加入法文、日文和韩文文档翻译。
  • 对模块属性访问的控制现在更容易了,因为 __getattr__ 现在可以在模块层次进行定义。这使得定制导入行为和实现特性,例如弃用警告,变得更加容易。
  • CPython 的一种新的开发模式
  • .pyc 文件具有确定性,支持可重复构建 —— 也就是说,总是为相同的输入文件生成相同的 byte-for-byte 输出。

有一些非常简洁的语法快捷方式和性能改进,但这可能不足以鼓励每个人进行升级。总的来说,Python 3.7 实现了一些特性,这些特性将真正减少混乱的代码解决方案,并生成更干净的代码。我们当然期待使用它,也等不及 3.8 的到来!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python 3.7 新特性概览(附实例

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python 3.7 新特性概览(附实例

译自:https://hackaday.com/2018/07/23/hands-on-with-python-3-7-whats-new-in-the-latest-release/?utm_source=mybridge&utm_med
2023-01-31

Python 3.9.0新特性实例分析

这篇文章主要介绍“Python 3.9.0新特性实例分析”,在日常操作中,相信很多人在Python 3.9.0新特性实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python 3.9.0新特性实例分析
2023-06-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录