「Python3学习笔记」读书笔记—字符串

字符串字面量以成对的单引号(`)、双引号(),或可跨行的三引号(”””)语法构成,自动合并相邻的字面量。字符串支持转义、八进制、十六进制,或 Unicode 格式字符。

使用单引号还是双引号,并没有什么特殊限制。如果文本内的引用文字使用双引号,那么外面用单引号可避免转义,更易阅读。

通常情况下,建议遵循多数编程语言惯例,使用双引号标示。

Python 3 中字符串存储的是 Unicode 文本,是不可变序列类型。而 Unicode 格式大小写分别表示 16 位( \u )和 32 位(\U)整数,不能混用。

>>> "h\x69, \u6C49\U00005B57"
'hi, 汉字'

在字面量前添加标志,表示构建指定格式的字符串。

>>> type(u"abc")
<class 'str'>
>>> type(b"abc")
<class 'bytes'>

最常用的原始字符串(r, raw string),它将反斜线视作字符内容,而非转义标志。这在构建类似 Windows 路径、正则表达式匹配模式之类的文法字符串时很有用。

>>> open(r"c:\windows\readme.txt”)

>>> import re
>>> re.findall(r"\b\d+\b", "a10 100")
['100']

操作

字符串支持用加法或乘法运算符拼接字符串。

>>> s = "hello"

>>> s += ", world"
>>> "-" * 10
'----------'

编译器会尝试在编译期直接计算出字面量拼接结果,可避免运行时的内存开销。不可此类优化程度有限,并不总是有效。

>>> def test():
...     a = "x" + "y" + "z"
...     b = "a" * 10
...     return a, b
...
>>> import dis
>>> dis.dis(test)
  2           0 LOAD_CONST               7 ('xyz')  # 直接给出结果,省略加法结果
              2 STORE_FAST               0 (a)

  3           4 LOAD_CONST               8 ('aaaaaaaaaa')   # 省略乘法运算
              6 STORE_FAST               1 (b)

  4           8 LOAD_FAST                0 (a)
             10 LOAD_FAST                1 (b)
             12 BUILD_TUPLE              2
             14 RETURN_VALUE

多个动态字符串拼接,应优先考虑 join 或 format 方式,而不是使用 + 号操作符直接拼接,这是因为相比于多次加法运算和多次内存分配(字符串是不可变对象),join 这类函数(方法)可预先计算出总长度,一次性分配内存,随后直接复制内存数据填充。另一方面,将固定模版内容与变量分离的 format,更易阅读和维护,可参考以前的这篇记录Python连接字符串优先使用join而不是+ | M-in’s Blog

编写代码时除保持简单外,还应具备良好的可读性。比如:判断是否包含子字符串,in、not in 操作符就比 find 方法自然,更贴近日常阅读习惯。

>>> "py" in "python"
True
>>> "py" not in "python"
False

>>> "python".find("py")
0

作为序列类型,可使用索引序号访问字符串的单个字符或某一片段(切片)。Python 3 支持负索引,也就是反向从尾部以 -1 开始(索引 0 表示正向第一个字符)。

>>> s = "0123456789"
>>> s[2]
'2'
>>> s[-1]
'9'
>>> s[2:6]
'2345'
>>> s[2:-2]
'234567'

无论以哪种方式返回与原字符串内容不同的子字符串时,都可能会重新分配内存,并复制数据。

转换

除了与数字、Unicode 码点的转化外,最常见的是在不用编码间进行转换。Python 3 使用 bytes、bytearray 存储字节序列,不再和 str 混用。

格式化

Python 3.6 新增了 f-strings 支持,这在多数脚本语言里属于标配。

使用 f 前缀标志,Python 解释器在解析大括号内的字段或表达式时,在上下文命名空间(namespace)查找同名对象进行值替换。

>>> x = 10
>>> y = 20
>>> f"{x} + {y} = {x + y}"
'10 + 20 = 30'

# 除运算符外,还可以是函数调用。
>>> f"{type(x)}"
"<class 'int'>"

完整的 format 格式化以位置序号或字段名匹配参数进行值替换,可添加对齐、填充、精度等控制。具体请参考官方文档6.1.3. Format String Syntax

池化

因为无处不在的名字就是字符串实例,导致字符串可能是进程里实例数量最多的类型之一。

鉴于相同的名字会出现在不同的命名空间里,那么有必要共享实例。内容相同,且不可变,共享内存不会导致任何问题。关键是节约内存,且可省去创建新实例的开销。

对此,Python 的做法是实现一个字符串池( intern )。

池负责管理实例,使用者只需饮用即可。另一潜在的好处是,从池返回的字符串,只需比较指针就可知道内容是否相同,无需额外计算。可以使用池来提升哈希表等类似结构的查找性能。

>>> import sys
>>> "__name__" is sys.intern("__name__")
True

除以常量方式出现的名字和字面量外,动态生成的字符串一样可加入池中。如此可保证每次都引用同一对象,不会有额外的创建和分配操作。

>>> a = "hello, world!"
>>> b = "hello, world!"
>>> a is b                                          # 不同实例
False
>>> sys.intern(a) is sys.intern("hello, world!")        # 相同实例
True

当然,一旦失去所有外部引用,池内的字符串对象一样会被回收。

>>> a = sys.intern("hello, world!")
>>> id(a)
4318361584
>>> id(sys.intern("hello, world!"))     # 有外部引用
4318361584

>>> del a                                   # 删除外部引用后被回收
>>> id(sys.intern("hello, world!"))     # 从 id 值不同可以看到字符串是新建后入池的
4318389808

字符串池的实现算法很简单,就是简单的字典结构。
详细可参考 Objects/unicodeobject.c : PyUnicode_InternInPlace。
做大数据处理时,可能须创建海量主键,使用类似机制有助于减少对象数量,节约大量内存。当然,可以选择更高效的数据结构,而不一定是系统内置的字符串池。

从博客搬运到简书:原文链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • Python 面向对象Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对...
    顺毛阅读 4,211评论 4 16
  • 字符串和字符 [TOC] 字符串是例如 "hello, world" , "albatross" 这样的有序的 C...
    伍哥___阅读 1,083评论 0 0
  • 前言 最先接触编程的知识是在大学里面,大学里面学了一些基础的知识,c语言,java语言,单片机的汇编语言等;大学毕...
    oceanfive阅读 3,049评论 0 7
  • 亲爱的 让你说喜欢我的那一刻起 我就发誓 如果你不离 我就不弃 !之后 你能天天能陪我聊天 我很是开心快乐 我恨...
    我要做她的男人阅读 190评论 0 0
  • (稻盛哲学学习会)打卡第64天 姓名:周琪 部门:业务部 组别:待定 【知~学习】 诵读《活法》第五章:与宇宙潮流...
    Lillian_Wellin阅读 121评论 0 0