8、Python中的字符串:字符串的基本操作及再论对象是否可变

引言

基于Python系列前面的几篇文章中,应该已经在脑海中对Python中的核心理念,有了一些认知,由于比较关键,这里再来回顾一下:

  • 1、Python中一切皆对象
  • 2、对象分为可变对象和不可变对象
  • 3、区分重新赋值操作,还是对象本身发生变化
  • 4、新手困惑的不可变对象的所谓的“对象修改”操作,一定是重新赋值操作,通过观察id()前后的变化,即可
  • 5、看似简单的一行代码一般都不是一步完成,而所谓字节码指令是能看到Python一行代码背后的实现步骤。

今天这篇文章,我们结合Python中的字符串的探究,再来进一步加深对这些理念的认知。

字符串的基本使用

Python中关于字符串的使用,相对来说是比较方便的。
关于字符串对象的创建、常用的一些方法,这里就不进行罗列了,随处都能查到,只要你能想到要对字符串进行的操作,Python大概也会有对应的方法,可以方便实现。关于字符串提供的方法,不用记忆,用到的时候,自行尝试或者检索即可,所以不再展开。

接下来,首先基于三个字母,对Python中提供的字符串使用的3个比较便捷的场景,其次,看一下Python中支持的字符串运算

26个字母至少要学会f/r/b

字母f对应的是字符串格式化,也就是常说的f-string语法糖。
关于字符串的格式化方法,前面关于print()函数的使用时,已经有所提及,这里不再展开,只是简要说明一下。需要知道的一点是,关于字符串的格式化,能使用f-string的时候,还是尽量使用f-string,在使用的便捷程度及底层实现上,Python已然做了足够多的优化,在使用过程中,可以自行体会:

name = '张三'
gender = '女's1 = "姓名: %s, 性别: %s" % (name, gender)
s2 = "姓名: {}, 性别: {}".format(name, gender)
s3 = f"姓名: {name}, 性别: {gender}"
print(s1)
print(s2)
print(s3)

字母r对应的字符串禁止自动转义的操作,默认情况下,字符串中以\打头的转义字符会进行自动化转义操作。如果需要保持字符串中的转义字符,在其他语言中一般是通过双反斜线\来实现,如果有多个转义字符,就需要多个地方都要改写,比较麻烦。
Python中不需要对原始字符串的内容进行修改,只需要在字符串开头加上一个r字母即可:

s1 = "hello world\n"
s2 = r"hello world\n"
print(s1)
print(s2)

执行结果:

字母b对应了字符串的转换为二进制编码的方法,关于字符串的编码、解码,可以简单演示一下,需要用到时,再做进一步深入:

s1 = "hello Python"
s2 = b"hello Python"
print(type(s1))
print(type(s2))
s3 = s1.encode('utf-8')
print(type(s3))
print(id(s2))
print(id(s3))
print(s2 == s3)
s4 = s2.decode('utf-8')
print(s4)
print(s1 == s4)

执行结果:


字符串前加上b,实际上是得到一个bytes对象,字符串对象和bytes对象之间可以通过encode()、decode()方法进行相互转换。

Python中的字符串运算

关于Python中的字符串运算,这里也不全面罗列,只是对比其他语言中,相对不同、觉得更加方便的用法,简单描述一下:
字符串拼接
Python中关于字符串的拼接,有多种方式,最简单的就是使用加法+;
如果使用相同的分割符也可以使用join()方法;
如果比较固定,还可以使用前面提到的f-string字符串格式化的方式,简单通过代码演示一下这些用法:

name = '张三'
gender = '女'
remark = 'Python大神'
s1 = name + ':' + gender + ':' + remark
s2 = ':'.join([name, gender, remark])
s3 = f"{name}:{gender}:{remark}"
print(s1)
print(s2)
print(s3)

执行结果:

字符串分割
Python中提供字符串分割的方法,返回包含各个子串的列表对象:

s1 = '张三:女:Python大神'
res = s1.split(':')
print(res)

执行结果:


通过查看split()方法的定义,可以看到有一个默认参数maxsplit=-1,设置该参数,可以指定从左到右最多的分割子串的个数,不再演示,可以自行尝试。

字符串相乘
Python支持字符串的乘法,可以实现字符串的快速重复操作,也比较简单,模仿《天龙八部》中的桥段:

s1 = '叩首千遍,心诚则灵:'
s2 = '叩首' * 1000
s3 = '汝即叩首千遍,足见心诚,传你无上Python功法,祝你叱咤江湖'
print('\n'.join([s1, s2, s3]))

执行结果:

字符串索引和切片
Python中的字符串也是可迭代的对象,支持索引和切片操作,方法基本同列表对象的索引和切片:

s1 = "hello Python"
# 索引操作,索引从0开始
print(s1[0])
# 切片操作,切片一般是,左闭右开:[start, end)
print(s1[:5])

执行结果:


关于更多的切片方式,参考列表的切片,可以自行研究。

字符串驻留的优化实现

字符串驻留(String Interning)是一种优化技术,由于字符串对象本身是不可变的,所以,当一个相同的字符串有可能被重复使用时,可以通过把某些字符串驻留在内存中,让这些引用相同字符串的变量,指向常量内存池中的同一个字符串对象,从而节省内存并提高运行速度。

此外,在进行字符串比较时,如果字符串对象驻留在驻留池中,只需要比较字符串的引用是否相同即可,而不需要进行逐字符比较。

不同的Python虚拟机中的实现细节可能不太一样,可以先粗略地理解为虚拟机内部会申请一块内存区域,用于字符串驻留,可以称之为字符串驻留池(intern pool)。当发现代码中需要创建一个新的字符串对象时,Python解释器会首先检查字符串驻留池,如果已经存在相同的字符串,则直接返回该字符串对象的引用,而不是创建一个新的字符串。

字符串驻留的思想,跟我们所熟知的缓存技术很是相似。
相似的还有缓存区、字符串驻留池的空间是有限的,不可能所有的字符串都进行驻留优化。

Python中字符串驻留的限制没有明确说明,不过,我们可以通过代码进行推测字符串驻留的行为机制:

s1 = 'a' * 100
s2 = 'a' * 100
print(id(s1))
print(id(s2))

通过修改字符串的长度,两个字符串的id()相同,则发生了驻留;如果id()不同,则没有发生驻留。可以从100~10000,进行二分查找,考虑到二进制,可以尝试1024、2048、4096等特殊长度。在笔者的环境中,字符串长度小于等于4096时,可以触发字符串驻留机制,一旦超过这个阈值,则不再进行字符串驻留。

s1 = 'a' * 4096
s2 = 'a' * 4096
print(id(s1))
print(id(s2))
s3 = 'a' * 4097
s4 = 'a' * 4097
print(id(s3))
print(id(s4))

执行结果:


s1与s2的id()是相同的,s3与s4的id()是不同的,可以验证上述的结论。

如果一个较长的字符串,只要你有需要,也是可以手动触发字符串驻留:

x = sys.intern('a' * 5000)
y = sys.intern('a' * 5000)
print(id(x))
print(id(y))

从字节码看实现字符串的不可变

还是开篇提到的字符串对象是可变的,我们前面提到的字符串相关的操作运算,看似字符串发生了改变。其实,在底层都是创建了新的字符串对象,然后进行了重新赋值操作。

name = '张三'
gender = '女'
s1 = f"{name}:{gender}"
# print(id(name))
# print(id(gender))
# print(id(s1))
# 实际是常量池中有一个字符串对象李四
name = '李四'
# print(id(name))

可以通过输出id(),看到操作前后,已经不是同一个对象。如果查看对应的字节码,可以更加清楚:

通过查看字节码,我们可以更清晰地看到字符串对象的创建与重新赋值操作。

这篇文章就先写到这里了,感谢您的阅读。

欢迎关注,持续分享更多好玩、好用的 Python 技术!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1473069.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Dos(命令符窗口)命令

目录 1. 常用Windows组合键 2. 常用DOS命令 3. 复制操作 4. 当前路径 5. 查看电脑ip地址 6. 切换盘符: 7. 目录 8. 自动补齐 8. 进入某路径:cd 路径 9. 直接进入某个位置 10. 新建文件 11. 查看文件内容 12. 关机 13. 强行终止命令的执行:C…

java基于ssm+vue 旅游信息资源平台

1前台首页功能模块 旅游资源网站 ,在系统首页可以查看首页、景点信息、酒店信息、客房信息、交流论坛、红色文化、个人中心、后台管理、客服等内容,如图1所示。 图1系统功能界面图 用户登录、用户注册,在注册页面可以填写用户名、密码、姓名…

如何第一次从零上传项目到GitLab

嗨,我是兰若,今天想给大家说下,如何上传一个完整的项目到与LDAP集成的GitLab,也就是说这个项目之前是不在git上面的,这是第一次上传,这样上传上去之后,其他小伙伴就可以根据你这个项目的git地址…

Maven 分模块设计与开发 继承

介绍 在 Maven 中进行分模块设计(multi-module project),可以帮助将一个大型项目分解为更小、更易管理的模块。这种设计方式有助于提高项目的可维护性、复用性和团队协作效率。 继承关系 目录结构 引入父Maven 父坐标 在子项目中引入父亲…

什么是 DDoS 攻击及如何防护DDOS攻击

自进入互联网时代,网络安全问题就一直困扰着用户,尤其是DDOS攻击,一直威胁着用户的业务安全。而高防IP被广泛用于增强网络防护能力。今天我们就来了解下关于DDOS攻击,以及可以防护DDOS攻击的高防IP该如何正确选择使用。 一、什么是…

Windows Server 2016 搭建 网络负载平衡 服务

网络负载平衡功能的安装 添加角色 默认不动————功能 勾选上 < 网络负载平衡 > 在工具中————打开 < 网络负载平衡管理器 > 网络负载平衡群集创建 注意 : 提前 将两台 web 站点服务器 都安装好 < 网络负载平衡功能 > 右键 选择 ————新建群集 ——…

【ONLYOFFICE8.1】ONLYOFFICE8.1版本桌面编辑器测评

有宝子说office太贵&#xff0c;不适合个人和学生&#xff0c;而WPS不仅贵广告还多&#xff0c;那么有没有一款软件可以替代office和WPS呢&#xff1f;...当然有喽。当当当当&#xff01;它就是众望所归、备受好评的ONLYOFFICE。下面就和小编一起来探索和测评一下ONLYOFFICE8.1…

Apache Flink架构介绍

目录 一、Apache Flink架构组件栈 1.1 概述 1.2 架构图 1.3 架构分层组件说明 1.3.1 物理部署层 1.3.2 Runtime 核心层 1.3.3 API & Libraries层 二、Flink运行时架构 2.1 概述 2.2 架构图 2.3 架构角色和组件 2.3.1 Flink Clients客户端 2.3.2 JobManager 2.…

[SAP ABAP] 函数Function

Function函数与子例程类似&#xff0c;按照功能将代码模块化 我们可以使用事务码SE37查看需要使用的函数以及对该函数进行测试 我们也可以对STRING_SPLIT_AT_POSITION函数进行测试 1.函数调用 我们可以使用事务码SE38进入ABAP编辑器界面&#xff0c;使用"模式/Pattern&q…

微信小程序:rpx详解,使用 tailwindcss最佳方案rem转rpx

rpx详解 不管手机的屏幕宽度是多少&#xff0c;微信小程序都负责把这个宽度平均分成 750 份&#xff0c;而把这分好过的 750 份中的 1 份取名叫 1rpx。 tailwindcss rem转rpx 配置 rem 转 rpx 安装配置好了 tailwindcss&#xff0c;接下来一步便是配置 rem 转 rpx tailwind…

视频共享融合赋能平台LnyonCVS国标视频监控平台包含哪些功能

随着国内视频监控应用的迅猛发展&#xff0c;系统接入规模不断扩大。不同平台提供商的接入协议各不相同&#xff0c;导致终端制造商在终端维护时需要针对不同平台的软件版本提供不同的维护&#xff0c;资源造成了极大的浪费。 为响应国家对重特大事件通过视频监控集中调阅来掌…

2025深圳国际人工智能展览会

2025深圳国际人工智能展览会 Shenzhen International Artificial Intelligence Exhibition 2025 时间&#xff1a;2025年6月25-27日 地点&#xff1a;深圳国际会展中心&#xff08;宝安新馆&#xff09; 详询主办方陆先生 I38&#xff08;前三位&#xff09; I82I&#…

Selenium 切换 frame/iframe

环境&#xff1a; Python 3.8 selenium3.141.0 urllib31.26.19说明&#xff1a; driver.switch_to.frame() # 将当前定位的主体切换为frame/iframe表单的内嵌页面中 driver.switch_to.default_content() # 跳回最外层的页面# 判断元素是否在 frame/ifame 中 # 126 邮箱为例 # …

Linux shell编程学习笔记62: top命令 linux下的任务管理器

0 前言 top命令是Unix 和 Linux下常用的性能分析工具&#xff0c;提供了一个动态的、交互式的实时视图&#xff0c;显示系统的整体性能信息&#xff0c;以及正在运行的进程的相关信息&#xff0c;包括各个进程的资源占用状况&#xff0c;类似于Windows的任务管理器。 1 top命令…

缓存与数据库数据一致性问题

在用了redis缓存的系统中&#xff0c;正常情况下&#xff0c;一个读操作会先查缓存&#xff0c;如果在缓存中查到了&#xff0c;则直接返回&#xff0c;如果缓存中没有&#xff0c;则会查数据库&#xff0c;再将查到的数据写到redis中&#xff0c;然后返回。如下图&#xff1a;…

如何在 Ubuntu上搭建 LAMP

远程登录 Ubuntu系统环境 ssh (User)(IP) # 比如&#xff1a;ssh lennlouis192.168.207.128 为安全起见&#xff0c;建议你使用 root 登录 VPS 后创建一个具有 sudo 权限的帐号。 安装和配置 Apache 2 Apache Http Server 是一个开源的&#xff0c;非常流行&#xff0c;使用…

Mysql中间件和高可用

文章目录 一、MySQL中间件代理服务器MycatMycat应用场景Mycat部署 实现读写分离 二、MySQL高可用高可用解决方案MHA高可用实现MHA 一、MySQL中间件代理服务器 数据库主要分为两大类&#xff1a;关系型数据库与 NoSQL 数据库&#xff08;非关系型数据库&#xff09;。 数据库主…

CASS7.0按方向和距离绘制图形

1、绘制工具 2、按方向和距离绘制 &#xff08;1&#xff09;切换方向 &#xff08;2&#xff09;距离输入

维护和管理LDAP之OpenDJ

目录 基本介绍 服务专有名词 安装 命令行工具 密码管理 重置管理员密码 管理服务器进程 管理索引 如何搜索 管理索引 管理目录数据 测试数据 导出数据 导入数据 LDIF文件数据查看和比较 数据存储-Backends 配置连接 开启 HTTP/HTTPS连接 使用 REST访问 -open…

多特征线性回归

目录 一、多特征符号意义说明&#xff1a;二、多特征模型表示&#xff1a;三、Numpy向量表示、内积计算&#xff1a;1.向量表示&#xff1a;2.内积计算&#xff1a; 四、多元线性回归梯度下降算法&#xff1a; 一、多特征符号意义说明&#xff1a; x下标j&#xff1a;表示第j个…