专栏首页北京马哥教育Python隐藏特性:字符串驻留、常量折叠

Python隐藏特性:字符串驻留、常量折叠

下面是Python字符串的一些微妙的特性,绝对会让你大吃一惊。

案例一:

>>> a = “some_string”

>>> id(a)

140420665652016

>>> id(“some” + “_” + “string”) # 注意两个的id值是相同的.

140420665652016

案例二:

>>> a = “wtf”

>>> b = “wtf”

>>> a is b

True

>>> a = “wtf!”

>>> b = “wtf!”

>>> a is b

False

>>> a, b = “wtf!”, “wtf!”

>>> a is b

True # 3.7 版本返回结果为 False.

案例三:

>>> ‘a’ * 20 is ‘aaaaaaaaaaaaaaaaaaaa’

True

>>> ‘a’ * 21 is ‘aaaaaaaaaaaaaaaaaaaaa’

False # 3.7 版本返回结果为 True

很好理解, 对吧?

讲解说明:

这些行为是由于 Cpython 在编译优化时, 某些情况下会尝试使用已经存在的不可变对象而不是每次都创建一个新对象. (这种行为被称作字符串的驻留[string interning])

发生驻留之后, 许多变量可能指向内存中的相同字符串对象. (从而节省内存)

在上面的代码中, 字符串是隐式驻留的. 何时发生隐式驻留则取决于具体的实现. 这里有一些方法可以用来猜测字符串是否会被驻留:所有长度为 0 和长度为 1 的字符串都被驻留.字符串在编译时被实现 (‘wtf’ 将被驻留, 但是 ”.join([‘w’, ‘t’, ‘f’]) 将不会被驻留)

字符串中只包含字母,数字或下划线时将会驻留. 所以 ‘wtf!’ 由于包含 ! 而未被驻留. 可以在【地址1】找到 CPython 对此规则的实现.

当在同一行将 a 和 b 的值设置为 “wtf!” 的时候, Python 解释器会创建一个新对象, 然后同时引用第二个变量(译: 仅适用于3.7以下, 详细情况请看【地址2】). 如果你在不同的行上进行赋值操作, 它就不会“知道”已经有一个 wtf! 对象 (因为 “wtf!” 不是按照上面提到的方式被隐式驻留的). 它是一种编译器优化, 特别适用于交互式环境.

常量折叠(constant folding) 是 Python 中的一种 窥孔优化(peephole optimization) 技术. 这意味着在编译时表达式 ‘a’*20会被替换为 ‘aaaaaaaaaaaaaaaaaaaa’ 以减少运行时的时钟周期. 只有长度小于 20 的字符串才会发生常量折叠. (为啥? 想象一下由于表达式 ‘a’*10**10 而生成的 .pyc 文件的大小). 相关的源码实现在【地址3】.

如果你是使用 3.7 版本中运行上述示例代码, 会发现部分代码的运行结果与注释说明相同. 这是因为在 3.7 版本中, 常量折叠已经从窥孔优化器迁移至新的 AST 优化器, 后者可以以更高的一致性来执行优化. (由 Eugene Toder 和 INADA Naoki 在 bpo-29469 和 bpo-11549 中贡献.)

(译: 但是在最新的 3.8 版本中, 结果又变回去了. 虽然 3.8 版本和 3.7 版本一样, 都是使用 AST 优化器. 目前不确定官方对 3.8 版本的 AST 做了什么调整.)

文章转载于马哥教育官网!

原文链接:https://www.magedu.com/84653.html

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【gitlab小症状】gitlab搭配ssh默认端口引发的血战

    困扰军哥的gitlab的ssh克隆为毛和别人不一样的问题 军哥的碰到的问题就像女神在看自己和镜子里的自己一样 ? 问题症状:ssh放的gitlab长得和别...

    小小科
  • Redis集群服务器-高可用调研随笔

    一、Redis与MySQL对比 相同点: Master-Slave架构,集群架构下无法很好的完成数据拷贝,确保数据一致性。 支持数据文件持久化存储,但数据文件...

    小小科
  • Python如何防止sql注入

    豌豆贴心提醒,本文阅读时间10分钟 前言 web漏洞之首莫过于sql了,不管使用哪种语言进行web后端开发,只要使用了关系型数据库,可能都会遇到sql注入攻...

    小小科
  • 索尼申请VR控制器新专利,大幅改进追踪功能 | 热点

    镁客网
  • Mysql的read_only 只读属性说明 (运维笔记)

    在MySQL数据库中,在进行数据迁移和从库只读状态设置时,都会涉及到只读状态和Master-Slave主从关系设置, 以下针对real_only只读属性做些笔记...

    洗尽了浮华
  • go 单元测试基本篇

    go 语言本身内置了一套相对轻量级的测试框架,通过 testing 库和 go test 命令支持单元测试。本篇文档主要介绍使用 go 语言 testing 包...

    腾讯云数据库团队
  • zoj ZOJ 3196 Give me the result

    http://acm.sdibt.edu.cn:8080/judge/contest/view.action?cid=579#problem/D 题意:给出一段...

    用户1624346
  • Redis 和 Memcached 的区别详解

    Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较:

    哲洛不闹
  • [译] BeyondProd:云原生安全的一种新方法(Google, 2019)

    本文翻译自 2019 年 Google 的一篇白皮书 BeyondProd: A new approach to cloud-native security, ...

    米开朗基杨
  • Redis与Memcached的区别

    本文我们将探讨 Redis (远程字典服务器). Redis是一个开源的、内存型的键值存储。它也被看作为一个字典型的数据结构服务器,因为它的键值不仅仅是字符串,...

    用户1263954

扫码关注云+社区

领取腾讯云代金券