详解Python中神奇的字符串驻留机制

目录
  • 1 什么是字符串驻留机制
  • 2 如何使用字符串驻留机制
  • 3 简单拼接驻留, 运行时不驻留
  • 4 总结
  • 5 全部代码

今天有一个初学者在学习Python的时候又整不会了。 原因是以下代码:

a = [1, 2, 3]
b = [1, 2, 3]
if a is b:
    print("a and b point to the same object")
else:
    print("a and b point to different objects")

运行结果是a and b point to different objects。

然后他又试了字符串对象。

str1 = "hello"
str2 = "hello"  

if str1 is str2:
    print("str1 and str2 are the same object")
else:
    print("str1 and str2 are different objects")

运行结果是:str1 and str2 are the same object

他找到田辛老师询问原因。 于是有了今天这篇文章:Python中的字符串驻留机制。

1 什么是字符串驻留机制

字符串驻留机制是Python针对字符串对象采取的一种内存优化技术。其目标是减少内存使用并提高程序的性能。

在Python中,字符串是不可变的对象,一旦创建,就不能被修改。因此,如果我们创建了两个字符串,它们将占用两个不同的内存位置。但是,如果这些字符串是相同的,那么它们将被Python自动合并为一个对象,这就是字符串驻留机制。

Python中的字符串驻留机制是通过使用intern机制来实现的。当我们创建一个字符串时,Python会检查字符串池中是否已经存在相同的字符串。如果是,它将返回现有的字符串对象的引用,而不是创建一个新的对象。这样,我们可以在不占用额外内存的情况下使用相同的字符串。

2 如何使用字符串驻留机制

Python的字符串驻留机制在不同版本之间有一些变化。下面是一些主要的变化:

1.Python 2.x和Python 3.x的字符串驻留机制不同。在Python 2.x中,只有长度为1的字符串才会被驻留。而在Python 3.x中,长度为0到20的字符串都会被驻留。 (更长的田辛老师试过,似乎都可以)

2.在Python 3.7之前,字符串驻留机制只适用于ASCII字符集中的字符串。这意味着只有ASCII字符集中的字符串才会被驻留。但是,在Python 3.7中,这个限制已经被取消,所有字符串都可以被驻留。

3.在Python 3.8中,字符串驻留机制的实现发生了变化。在之前的版本中,字符串池是一个全局的数据结构,所有的字符串都存储在其中。但是,在Python 3.8中,字符串池被改为了一个线程局部的数据结构,每个线程都有自己的字符串池。这样可以提高多线程程序的性能。

需要注意的是,字符串驻留机制是Python的一种优化技术,它并不是Python语言规范的一部分。因此,不同的Python实现(如CPython、Jython、IronPython等)可能会有不同的字符串驻留机制实现。

正是因为上面的变化, 所以有的时候田辛老师觉得字符串驻留在面向内存的时候是友好的, 但确实会给新手带来一些不便。

作为新手, 田辛老师提供一个手动使用字符串驻留的例子:

import sys 

# 使用sys.intern()函数启用字符串驻留机制
str3 = sys.intern("hello")
str4 = sys.intern("hello") 

# 使用is关键字比较两个字符串是否相同
if str3 is str4:
    print("str3 and str4 are the same object")
else:
    print("str3 and str4 are different objects")

上面的例子中,田辛老师使用sys.intern()函数将字符串“hello”添加到字符串池中,并将返回的引用分配给str3和str4。然后,我们再次使用is关键字比较它们是否相同。由于它们是相同的对象,因此输出结果为“str3 and str4 are the same object”。

3 简单拼接驻留, 运行时不驻留

我们来看下面的代码:

str5 = 'tianxin' + 'training'
print(str5 is 'tianxintraining')  

str6 = 'tianxin'
str7 = 'training'
print((str6 + str7) is 'tianxintraining')

大家可以猜一猜输出结果是什么? 是两个true,还是一个true一个false?

答案是:

True
False

为什么会出现这种情况呢? 第一个打印,是两个字符串简单拼接, 那么就会实现字符串驻留。 但是, 一旦是变量拼接字符串机制就不能用了。

关于这一点, 田辛老师通过如下代码带领大家查看一下上述两个处理的汇编执行过程:

import dis  

def pro1():
    str5 = 'tianxin' + 'training'
    print(str5 is 'tianxintraining')  

def pro2():
    str6 = 'tianxin'
    str7 = 'training'
    print((str6 + str7) is 'tianxintraining')  

print('================================================================')
dis.dis(pro1)
print('================================================================')
dis.dis(pro2)

输出结果:

================================================================
 20           0 LOAD_CONST               1 ('tianxintraining')
              2 STORE_FAST               0 (str5)

21           4 LOAD_GLOBAL              0 (print)
              6 LOAD_FAST                0 (str5)
              8 LOAD_CONST               1 ('tianxintraining')
             10 IS_OP                    0
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE
================================================================
 25           0 LOAD_CONST               1 ('tianxin')
              2 STORE_FAST               0 (str6)

26           4 LOAD_CONST               2 ('training')
              6 STORE_FAST               1 (str7)

27           8 LOAD_GLOBAL              0 (print)
             10 LOAD_FAST                0 (str6)
             12 LOAD_FAST                1 (str7)
             14 BINARY_ADD
             16 LOAD_CONST               3 ('tianxintraining')
             18 IS_OP                    0
             20 CALL_FUNCTION            1
             22 POP_TOP
             24 LOAD_CONST               0 (None)
             26 RETURN_VALUE

进程已结束,退出代码0

我们可以看到, Python的解释器对这种简单的字符串拼接在形成字符码的时候,就已经进行了拼接。 str5 你写不写成拼接的形式都是一样的。

4 总结

Python的字符串驻留机制是一种优化技术,它可以减少内存使用并提高程序的性能。它的做法的基础是Python字符串对象的不可改变的特性。 当然, 不同的Python版本对于字符串驻留机制的处理不同可能会给初学者带来一些麻烦。 Python学习者必须要面对的一个问题。

5 全部代码

上面已经有了关于输出汇编的全部代码, 就不再重新输出了。 只展示字符串驻留部分的代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
#-----------------------------------------------------------------------------
#                     --- TDOUYA STUDIOS ---
#-----------------------------------------------------------------------------
#
# @Project : di08-tdd-cdg-python-learning
# @File    : str_intern.py
# @Author  : tianxin.xp@gmail.com
# @Date    : 2023/4/5 10:34
#
# 代码说明
#
#--------------------------------------------------------------------------"""
import sys  

a = [1, 2, 3]
b = [1, 2, 3]
if a is b:
    print("a and b point to the same object")
else:
    print("a and b point to different objects")  

str1 = "hello"
str2 = "hello"  

if str1 is str2:
    print("str1 and str2 are the same object")
else:
    print("str1 and str2 are different objects")  

# 使用sys.intern()函数启用字符串驻留机制
str3 = sys.intern("hello")
str4 = sys.intern("hello")  

# 使用is关键字比较两个字符串是否相同
if str3 is str4:
    print("str3 and str4 are the same object")
else:
    print("str3 and str4 are different objects")  

str5 = 'tianxin' + 'training'
print(str5 is 'tianxintraining')  

str6 = 'tianxin'
str7 = 'training'
print((str6 + str7) is 'tianxintraining')

执行结果:警告可忽略

D:\python-grp\miniconda_env\py3.10\python.exe E:\develop\python\di08-tdd-cdg-python-learning\src\std_str_intern\str_intern.py 
a and b point to different objects
str1 and str2 are the same object
str3 and str4 are the same object
True
False
E:\develop\python\di08-tdd-cdg-python-learning\src\std_str_intern\str_intern.py:44: SyntaxWarning: "is" with a literal. Did you mean "=="?
  print(str5 is 'tianxintraining')
E:\develop\python\di08-tdd-cdg-python-learning\src\std_str_intern\str_intern.py:48: SyntaxWarning: "is" with a literal. Did you mean "=="?
  print((str6 + str7) is 'tianxintraining')

进程已结束,退出代码0

到此这篇关于详解Python中神奇的字符串驻留机制的文章就介绍到这了,更多相关Python字符串驻留机制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python 字符串的驻留机制及优缺点

    说明 字符串驻留是一种仅保存一份相同且不可变字符串的方法.不同的值被存放在字符串驻留池中,发生驻留之后, 许多变量可能指向内存中的相同字符串对象, 从而节省内存. 原理 系统维护interned字典,记录已被驻留的字符串对象 当字符串对象a需要驻留时,先在interned检测是否存在,若存在则指向存在的字符串对象,a的引用计数减1 若不存在,则记录a到interned中 驻留时机 所有长度为 0 和长度为 1 的字符串都被驻留 字符串只在编译时进行驻留,而非运行时 a = 'hi' # a变量被

  • python学习字符串驻留与常量折叠隐藏特性详解

    下面是Python字符串的一些微妙的特性,绝对会让你大吃一惊. 案例一: 案例二: 案例三: 很好理解, 对吧? 说明: 这些行为是由于 Cpython 在编译优化时, 某些情况下会尝试使用已经存在的不可变对象而不是每次都创建一个新对象. (这种行为被称作字符串的驻留[string interning]) 发生驻留之后, 许多变量可能指向内存中的相同字符串对象. (从而节省内存) 在上面的代码中, 字符串是隐式驻留的. 何时发生隐式驻留则取决于具体的实现. 这里有一些方法可以用来猜测字符串是否会

  • Python字符串的创建和驻留机制详解

    目录 字符串 字符串驻留机制 字符串驻留机制优缺点 字符串 字符串在Python中是基本数据类型,是一个不可变的字符序列. 字符串驻留机制 仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量. 驻留机制的几种情况(交互模式windows+r,cmd) 1.字符串的长度为0或1时 2.符合标识符的字符串 3.字符串只在编译时进行驻留,而非运行时 b在运行

  • Python中的 is 和 == 以及字符串驻留机制详解

    is 和 == 先了解下官方文档中关于 is 和 == 的概念.is 表示的是对象标示符(object identity),而 == 表示的是相等(equality):is 的作用是用来检查对象的标示符是否一致,也就是比较两个对象在内存中的地址是否一样(相当于检查 id(a) == id(b)),而 == 是用来检查两个对象引用的值是否相等(相当于检查 a.eq(b)):这点和Java有点类似,只不过Java中是用 == 来比较两个对象在内存中的地址,用 equals() 来检查两者之间的值是否

  • python字符串驻留机制的使用范围知识点详解

    1.字符串的长度为0和1时. 2.符合标识符的字符串. 3.字符串只在编译时进行驻留,而非运行时. 4.[-5,256]之间的整数数字. 实例 >>> str1='jiumo' >>> str2='jiumo' >>> str1 is str2 True >>> id(str1) 1979078421896 >>> id(str2) 1979078421896 知识点扩充: 驻留时机 所有长度为 0 和长度为 1 的

  • 详解python字符串驻留技术

    前言 每种编程语言为了表现出色,并且实现卓越的性能,都需要有大量编译器级与解释器级的优化. 由于字符串是任何编程语言中不可或缺的一个部分,因此,如果有快速操作字符串的能力,就可以迅速地提高整体的性能. 在本文中,我们将深入研究 Python 的内部实现,并了解 Python 如何使用一种名为字符串驻留(String Interning)的技术,实现解释器的高性能.本文的目的不仅在于介绍 Python 的内部知识,而且还旨在使读者能够轻松地浏览 Python 的源代码:因此,本文中将有很多出自CP

  • 详解Python中神奇的字符串驻留机制

    目录 1 什么是字符串驻留机制 2 如何使用字符串驻留机制 3 简单拼接驻留, 运行时不驻留 4 总结 5 全部代码 今天有一个初学者在学习Python的时候又整不会了. 原因是以下代码: a = [1, 2, 3] b = [1, 2, 3] if a is b: print("a and b point to the same object") else: print("a and b point to different objects") 运行结果是a an

  • 详解Python中键盘鼠标的相关操作

    目录 一.前言 二.pyautogui模块 三.鼠标相关操作 1.鼠标移动 2.获取鼠标位置 3.鼠标点击 4.按松鼠标 5.拖动窗口 6.上下滑动 7.小程序——鼠标操控术2.0 8.小程序——连点器 四.键盘相关操作 1.按键的按松 2.键入字符串 3.热键 4.小程序——轰炸器 5.小程序——520个我爱你 五.尾声 一.前言 恭喜你,学明白类,你已经学会所有基本知识了. 这章算是一个娱乐篇,十分简单,了解一下pyautogui模块,这算是比较好学还趣味性十足的,而且可以做许多小程序. 本

  • 详解Python中pyautogui库的最全使用方法

    在使用Python做脚本的话,有两个库可以使用,一个为PyUserInput库,另一个为pyautogui库.就本人而言,我更喜欢使用pyautogui库,该库功能多,使用便利.下面给大家介绍一下pyautogui库的使用方法.在cmd命令框中输入pip3 install pyautogui即可安装该库! 常用操作 我们在pyautogui库中常常使用的方法,如下: import pyautogui pyautogui.PAUSE = 1 # 调用在执行动作后暂停的秒数,只能在执行一些pyaut

  • 详解Python中namedtuple的使用

    namedtuple是Python中存储数据类型,比较常见的数据类型还有有list和tuple数据类型.相比于list,tuple中的元素不可修改,在映射中可以当键使用. namedtuple: namedtuple类位于collections模块,有了namedtuple后通过属性访问数据能够让我们的代码更加的直观更好维护. namedtuple能够用来创建类似于元祖的数据类型,除了能够用索引来访问数据,能够迭代,还能够方便的通过属性名来访问数据. 接下来通过本文给大家分享python nam

  • 详解Python中第三方库Faker

    项目开发初期,为了测试方便,我们总要造不少假数据到系统中,尽量模拟真实环境. 比如要创建一批用户名,创建一段文本,电话号码,街道地址.IP地址等等. 平时我们基本是键盘一顿乱敲,随便造个什么字符串出来,当然谁也不认识谁. 现在你不要这样做了,用Faker就能满足你的一切需求. 1. 安装 pip install Faker 2. 简单使用 >>> from faker import Faker >>> fake = Faker(locale='zh_CN') >&

  • 详解Python中string模块除去Str还剩下什么

    string模块可以追溯到早期版本的Python. 以前在本模块中实现的许多功能已经转移到str物品. 这个string模块保留了几个有用的常量和类来处理str物品. 字符串-文本常量和模板 目的:包含用于处理文本的常量和类. 功能 功能capwords()将字符串中的所有单词大写. 字符串capwords.py import string s = 'The quick brown fox jumped over the lazy dog.' print(s) print(string.capw

  • 详解python中的异常和文件读写

    Python异常 1.python异常的完整语法 try: # 提示用户输入一个整数 num = int(input("输入一个整数:")) # 使用 8 除以用户输入的整数并且输出 result = 8 / num print(result) except ValueError: print("请输入正确的整数!") except Exception as result: print("未知错误:%s" % result) else: prin

  • 详解python中的IO操作方法

    目录 python文件I/O raw_input函数 input函数 打开和关闭文件 open 函数 file对象的属性 close()方法 write()方法 read()方法 Python with open as函数 python文件I/O 打印到屏幕: 最简单的输出方法是用print语句,你可以给它传递零个或多个用逗号隔开的表达式. 读取键盘输入: Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘.如下: raw_input input raw_input函数

  • 详解Python中的自定义密码验证

    目录 在测试:nut_and_bolt:️之前 试验contains_character TestContainsCharacter字符 试验is_valid_size TestIsValidSize 试验is_valid_password TestIsValidPassword 重构is_valid_password 结论 这些帖子将分为三个部分. 1.密码验证功能 2.重构密码验证函数 3.对密码验证功能进行单元测试 这是Python系列中自定义密码验证的第三部分,也是最后一部分.我们将看看

  • 详解Python中sorted()和sort()的使用与区别

    目录 sort()方法是什么 如何妙用sorted() 方法 总结 在 Python 中,你可以使用 sorted() 方法或 sort() 方法对数据进行排序. 在本文中,我将提供 sorted() 和 sort() 方法的代码示例,并解释两者之间的区别. sort()方法是什么 此方法接受一个列表并对其进行排序.但,请记住此方法没有返回值,即返回None. 下面例子中,我们有一个数字列表,我们可以使用 sort() 方法按升序对列表进行排序. my_list = [67, 2, 999, 1

随机推荐