百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

一文掌握Python 的字符串驻留是如何工作的

off999 2024-09-14 07:08 29 浏览 0 评论

Python 是一种灵活的编程语言,它提供了各种机制来优化性能和内存使用情况。其中一种优化技术就是字符串驻留。

字符串驻留

字符串驻留是一个根植于内存和性能优化的概念,尤其是在 Python 等编程语言中。

什么是字符串驻留?

字符串驻留的核心是只存储每个不同不可变字符串值的一个副本。不可变字符串一旦创建就无法更改。这种不变性是驻留过程的关键,因为它确保存储的字符串值保持不变,从而允许多个引用安全地指向同一内存位置。

当一个字符串被驻留时,任何其他具有相同值的字符串都将引用相同的内存位置。这意味着 Python 不会为相同的字符串创建新的内存分配,而是重用现有的内存分配。这种重用使字符串驻留成为一种有效的优化技术。

为什么字符串驻留很有用?

字符串驻留有几个显著的好处:

  1. 内存效率:通过仅存储相同字符串的一个副本,Python 减少了使用的内存量。这对于处理大量重复字符串值的应用程序(例如文本处理、数据解析和日志系统)尤其有益。
  2. 性能改进:驻留字符串可以加快比较速度。通常,比较两个字符串需要逐个检查每个字符,这对于长字符串来说可能非常耗时。但是,如果字符串被驻留,Python 可以简单地比较它们的内存地址。如果地址相同,则字符串相等。这种指针比较比逐个字符比较快得多。
  3. 一致性和安全性:字符串驻留有助于保持一致性,并避免因拥有同一字符串的多个副本而可能出现的潜在错误。由于驻留字符串是不可变的且存储在单个位置,因此无意中修改一个字符串(如果字符串是可变的)不会影响其他字符串,从而确保数据完整性。

何时应使用字符串驻留?

了解字符串驻留有益的场景可以帮助您做出明智的决定,确定何时在代码中使用它:

  1. 重复字符串的高频率:如果您的应用程序涉及处理大量重复字符串,则驻留可以显著节省内存并提高性能。
  2. 性能关键的字符串比较:在字符串比较是性能瓶颈的情况下,实习可以通过利用指针相等性检查而不是逐个字符的比较来加快比较速度。
  3. 资源受限的环境:在内存受限的环境中,例如嵌入式系统或在有限硬件上运行的应用程序,驻留可以帮助优化内存使用情况。

限制和注意事项

虽然字符串驻留提供了明显的好处,但重要的是要注意它的局限性:

  • 内存开销:驻留需要在内存节省和管理驻留字符串池的开销之间进行权衡。驻留过多的字符串(尤其是较大的字符串)可能会导致驻留字符串池本身的内存使用量增加。
  • 垃圾回收:只要引用了 Interned 字符串,它们通常就不会被垃圾回收。如果 Interned 字符串使用不当,则可能会导致内存泄漏。
  • 并非总是自动:Python 不会自动驻留所有字符串。了解何时手动驻留字符串对于实现所需的性能和内存优势至关重要。

Python 中的字符串驻留是如何工作的

Python 的字符串驻留机制在优化内存使用和提高性能方面起着至关重要的作用。了解 Python 中字符串驻留的工作原理需要探索自动和手动驻留过程,并识别发生驻留的具体场景。

自动驻留

Python 会自动保留某些字符串以优化内存使用和性能。此过程是隐式的,通常涉及类似于标 识符且经常重复使用的字符串。

标识符的驻留

Python 中的标识符(例如变量名和函数名)会自动保留。这些标识符通常由字母数字字符和下划线组成。Python 之所以保留这些字符串,是因为它们在程序执行过程中被广泛使用且经常被比较。

示例:标识符的自动驻留

a = 'name'
 b = 'name' 
print (a is b)   # 输出:True

 x = 'variable_1'
 y = 'variable_1' 
print (x is y)   # 输出:True

在此示例中,字符串'name''variable_1'由 Python 自动驻留。因此,ab引用相同的内存位置,与x和一样y

短字符串

Python 还会驻留短字符串,通常是长度少于 20 个字符的字符串。这些短字符串通常会在程序中重复使用,驻留它们可以显著减少内存使用量。

示例:自动驻留短字符串

a = 'short'
 b = 'short' 
print (a is b)   # 输出: True

 m = 'longer_string_that_is_not_interned'
 n = 'longer_string_that_is_not_interned' 
print (m is n)   # 输出: False

在此示例中,短字符串'short'会自动驻留,因此ab引用相同的内存位置。但是,较长的字符串'longer_string_that_is_not_interned'不会自动驻留,因此mn引用不同的内存位置。

手动驻留

对于未自动驻留的字符串,Python 提供了一种使用模块sys.intern()中的函数手动驻留它们的机制sys。当处理较大的字符串或不符合自动驻留标准的字符串时,这很有用。

使用sys.intern()

sys.intern()函数确保相同的字符串共享相同的内存位置,即使它们没有被 Python 自动驻留。

示例:手动驻留sys.intern()

import sys

a = 'unique_string'
 b = 'unique_string' 
print (a is b)   # 输出:False

 a = sys.intern( 'unique_string' ) 
b = sys.intern( 'unique_string' ) 
print (a is b)   # 输出:True

在此示例中,字符串'unique_string'不会自动驻留,因此ab最初引用不同的内存位置。使用之后sys.intern()a和都b引用相同的内存位置,这表明字符串已被手动驻留。

编译期间驻留

Python 还会在编译过程中驻留字符串,尤其是那些出现在函数定义和类定义中的字符串。这意味着在编译时创建的字符串通常会被驻留以优化内存使用并提高性能。

示例:编译时字符串驻留

defgreet ():return'hello'a = greet()b= 'hello'print ( a is b)   #输出:True
     



在此示例中,字符串'hello'在函数编译期间被驻留greet。因此,a和都b引用相同的内存位置。

字符串驻留的含义

字符串驻留会对内存使用和性能产生重大影响。通过了解 Python 何时以及如何驻留字符串,开发人员可以编写更高效、更优化的代码。

内存使用情况

通过确保相同的字符串仅存储一次,驻留字符串可以减少程序的总体内存占用。这对于处理大量重复字符串值的应用程序尤其有益。

示例:通过 Interning 节省内存

import sys 

str_list = [sys.intern( 'repeat' ) for _ in  range ( 1000 )] 
print (str_list[ 0 ] is str_list[ 999 ])   # 输出:True

在此示例中,使用sys.intern()确保字符串的所有 1000 个实例都'repeat'引用相同的内存位置,从而节省大量内存。

性能改进

内置字符串允许更快的比较,因为它们启用了指针相等性检查,而不是逐个字符的比较。这可以在字符串比较是关键操作的应用程序中带来明显的性能提升。

示例:使用 Interning 进行更快的字符串比较

a = sys.intern( 'compare_me' ) 
b = sys.intern( 'compare_me' ) 

if a is b: 
    print ( '字符串相同(快速比较)' ) 
else : 
    print ( '字符串不相同' )

a在这个例子中,和之间的比较b很快,因为它涉及检查它们的内存地址。如果字符串没有被驻留,比较将涉及检查每个字符,这会更慢。

字符串驻留发生的场景

Python 中的字符串驻留并不总是可预测的,但在某些情况下它经常发生。识别这些场景可以帮助您有效利用字符串驻留来优化内存使用和性能。

短字符串和标识符

Python 默认会保留短字符串和标识符。标识符是可用作变量名的字符串,例如字母数字字符串和下划线。短字符串(通常少于 20 个字符)也会自动保留。

示例:Interned 标识符

a = 'name'
 b = 'name' 
print (a is b)   # 输出:True

 x = 'name_1'
 y = 'name_1' 
print (x is y)   # 输出:True

在这些示例中,字符串namename_1被保留,因为它们看起来像标识符,并且由字母数字字符和下划线组成。因此,ab引用相同的内存位置,就像x和 一样y

编译时创建的字符串

在编译时创建的字符串(例如函数定义中使用的字符串)通常会被驻留。这是因为 Python 将源代码编译为字节码,在此过程中,某些字符串会被驻留以优化内存使用并提高性能。

示例:编译时字符串

defgreet ():return'hello'a = greet()b= 'hello'print ( a is b)   #输出:True
     



hello在此示例中,函数返回的字符串greet在函数编译期间被驻留。因此,a和都b引用相同的内存位置。

明确驻留sys.intern()

对于未自动驻留的字符串,您可以使用该sys.intern()方法显式地驻留它们。这对于较长或不符合自动驻留标准但仍在程序中频繁使用或比较的字符串特别有用。

示例:显式驻留

导入系统

a = '唯一字符串'
 b = '唯一字符串' 
print (a is b)   # 输出:False

 a = sys.intern( '唯一字符串' ) 
b = sys.intern( '唯一字符串' ) 
print (a is b)   # 输出:True

在此示例中,字符串unique string不会自动驻留,因此ab最初引用不同的内存位置。使用之后sys.intern()a和都b引用相同的内存位置,这表明字符串已被手动驻留。

大量字符串

在应用程序处理大量字符串的场景中(例如处理文本数据、解析文件或处理大型数据集),字符串驻留可以显著节省内存并提高性能。通过驻留重复的字符串,您可以减少总体内存占用并加快字符串比较操作的速度。

import sys 

words = [ 'interned_word' ] * 1000
 interned_words = [sys.intern(word) for word in words] 

print (interned_words[ 0 ] is interned_words[ 999 ])   # 输出:True

在此示例中,列表words包含 1000 个字符串实例interned_word。通过使用sys.intern(),字符串的所有实例都将被保留,从而节省大量内存。因此,列表的第一个和最后一个元素interned_words引用相同的内存位置。

缓存和记忆

缓存和记忆技术通常涉及存储昂贵的函数调用的结果以避免冗余计算。在这些情况下,字符串驻留可以减少内存使用量并加快缓存字符串的比较速度,从而大有裨益。

示例:使用 Interned 字符串进行缓存

导入系统

缓存 = {} 

def  expensive_function(param):
    param = sys.intern(param)
    如果缓存中的参数:
        返回缓存[param]
    结果= compute_expensive_result(param)
    缓存[param] = result
    返回结果

在此示例中,在检查缓存之前,expensive_function先实习字符串。这可确保相同的字符串引用相同的内存位置,从而使缓存查找更加高效。param

性能关键型应用程序

在性能至关重要的应用程序中,例如那些需要频繁进行字符串比较或在内存受限的环境中运行的应用程序,字符串驻留可以带来巨大的好处。通过驻留字符串,您可以优化内存使用率和字符串操作的速度。

示例:性能关键型字符串比较

导入系统

a = sys.intern( 'performance' ) 
b = sys.intern( 'performance' )

如果a是b:
    print ( '字符串相同(快速比较)' ) 
else:
    print ( '字符串不相同' )

a在这个例子中,和之间的比较b很快,因为它涉及检查它们的内存地址。如果字符串没有被驻留,比较将涉及检查每个字符,这会更慢。

结论

Python 中的字符串驻留是一种强大的优化技术,通过仅存储相同的不可变字符串的一个副本来提高内存效率和性能。通过自动驻留标识符和短字符串,Python 可以节省内存并加快字符串比较速度。sys.intern()对于不适用自动驻留的场景,开发人员还可以使用该函数手动驻留字符串。

了解字符串驻留发生的方式和时间可以帮助您做出明智的决策来优化 Python 代码,尤其是在处理大量字符串、性能关键操作和内存受限环境的应用程序中。通过正确利用字符串驻留,您可以确保您的程序运行得更高效并更好地利用可用资源。

相关推荐

让 Python 代码飙升330倍:从入门到精通的四种性能优化实践

花下猫语:性能优化是每个程序员的必修课,但你是否想过,除了更换算法,还有哪些“大招”?这篇文章堪称典范,它将一个普通的函数,通过四套组合拳,硬生生把性能提升了330倍!作者不仅展示了“术”,更传授...

7 段不到 50 行的 Python 脚本,解决 7 个真实麻烦:代码、场景与可复制

“本文整理自开发者AbdurRahman在Stackademic的真实记录,所有代码均经过最小化删减,确保在50行内即可运行。每段脚本都对应一个日常场景,拿来即用,无需额外依赖。一、在朋...

Python3.14:终于摆脱了GIL的限制

前言Python中最遭人诟病的设计之一就是GIL。GIL(全局解释器锁)是CPython的一个互斥锁,确保任何时刻只有一个线程可以执行Python字节码,这样可以避免多个线程同时操作内部数据结...

Python Web开发实战:3小时从零搭建个人博客

一、为什么选Python做Web开发?Python在Web领域的优势很突出:o开发快:Django、Flask这些框架把常用功能都封装好了,不用重复写代码,能快速把想法变成能用的产品o需求多:行业...

图解Python编程:从入门到精通系列教程(附全套速查表)

引言本系列教程展开讲解Python编程语言,Python是一门开源免费、通用型的脚本编程语言,它上手简单,功能强大,它也是互联网最热门的编程语言之一。Python生态丰富,库(模块)极其丰富,这使...

Python 并发编程实战:从基础到实战应用

并发编程是提升Python程序效率的关键技能,尤其在处理多任务场景时作用显著。本文将系统介绍Python中主流的并发实现方式,帮助你根据场景选择最优方案。一、多线程编程(threading)核...

吴恩达亲自授课,适合初学者的Python编程课程上线

吴恩达教授开新课了,还是亲自授课!今天,人工智能著名学者、斯坦福大学教授吴恩达在社交平台X上发帖介绍了一门新课程——AIPythonforBeginners,旨在从头开始讲授Python...

Python GUI 编程:tkinter 初学者入门指南——Ttk 小部件

在本文中,将介绍Tkinter.ttk主题小部件,是常规Tkinter小部件的升级版本。Tkinter有两种小部件:经典小部件、主题小部件。Tkinter于1991年推出了经典小部件,...

Python turtle模块编程实践教程

一、模块概述与核心概念1.1turtle模块简介定义:turtle是Python标准库中的2D绘图模块,基于Logo语言的海龟绘图理念实现。核心原理:坐标系系统:原点(0,0)位于画布中心X轴:向右...

Python 中的asyncio 编程入门示例-1

Python的asyncio库是用于编写并发代码的,它使用async/await语法。它为编写异步程序提供了基础,通过非阻塞调用高效处理I/O密集型操作,适用于涉及网络连接、文件I/O...

30天学会Python,开启编程新世界

在当今这个数字化无处不在的时代,Python凭借其精炼的语法架构、卓越的性能以及多元化的应用领域,稳坐编程语言排行榜的前列。无论是投身于数据分析、人工智能的探索,还是Web开发的构建,亦或是自动化办公...

Python基础知识(IO编程)

1.文件读写读写文件是Python语言最常见的IO操作。通过数据盘读写文件的功能都是由操作系统提供的,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个...

Python零基础到精通,这8个入门技巧让你少走弯路,7天速通编程!

Python学习就像玩积木,从最基础的块开始,一步步搭建出复杂的作品。我记得刚开始学Python时也是一头雾水,走了不少弯路。现在回头看,其实掌握几个核心概念,就能快速入门这门编程语言。来聊聊怎么用最...

一文带你了解Python Socket 编程

大家好,我是皮皮。前言Socket又称为套接字,它是所有网络通信的基础。网络通信其实就是进程间的通信,Socket主要是使用IP地址,协议,端口号来标识一个进程。端口号的范围为0~65535(用户端口...

Python-面向对象编程入门

面向对象编程是一种非常流行的编程范式(programmingparadigm),所谓编程范式就是程序设计的方法论,简单的说就是程序员对程序的认知和理解以及他们编写代码的方式。类和对象面向对象编程:把...

取消回复欢迎 发表评论: