一、不可变对象
不可变对象的定义:是一种对象,在被创造之后,它的状态( 对象的数据 )就不可以被改变。
在 Python 这门语言中,字符串属于不可变对象,一旦我们要对原有字符串进行修改,那么我们只能创建新的字符串对象。
测试代码
a = '123'
print('a = ' + a, 'address = ' + str(id(a)))
a = '124'
print('a = ' + a, 'address = ' + str(id(a)))
测试结果
a = 123 address = 2220275399536
a = 124 address = 2220275091504
由测试结果,可以看到,当字符串对象发生改变时,id值也发生了变化,所以说明字符串对象时不可变对象。如图
二、字符串的拼接
在 Python 中,字符串的拼接有两种方式,一种是用 + 拼接,另一种时用 join( ) 函数拼接。
用 + 拼接字符串时,会创建新的对象。怎么理解呢?
例子:str = str1 + str2 + str3,那么在 Python 中,首先会将 str1 与 str2 拼接,创建一个新的对象,再将这个新的对象与 str3 拼接,再次创建一个新的对象,所以我们可以总结出,如果有 N 个字符串相加,其中会创建 N - 1 次对象。
用 join( ) 函数,则只会创建一次对象。因为 join( ) 函数在拼接字符串之前会计算所有字符串的长度,然后逐一拷贝,仅新建一次对象。
在 Python 中,字符串拼接,比较推荐的方式是利用 join( ) 函数拼接,效率会比 + 要高。接下来,我们用代码来测试一下~
测试代码
import time
a = ''
aStart = time.time()
for _ in range(2000000):
a += 'str'
aEnd = time.time()
print('利用 + 拼接字符串的时间是: {:.2}'.format(aEnd - aStart))
b = []
bStart = time.time()
for _ in range(2000000):
b.append('str')
''.join(b)
bEnd = time.time()
print('利用 join() 拼接字符串的时间是: {:.2}'.format(bEnd - bStart))
测试结果
利用 + 拼接字符串的时间是: 1.1
利用 join() 拼接字符串的时间是: 0.16
通过结果可以看到,利用 join( ) 拼接字符串的速度是 + 拼接字符串速度的近 7 倍,所以拼接字符串时,我们尽量使用 join( ) 函数。
三、字符串的驻留机制
驻留机制的定义:仅保存一份相同且不可变字符串,不同的值被存放在字符串驻留池中。
Python 支持字符串驻留机制,对于符合标识符规则的字符串,会启用字符串驻留机制驻留机制。
测试代码-1
str1 = 'abc'
str2 = 'abc'
print('str1 = ' + str1, 'address = ' + str(id(str1)))
print('str2 = ' + str2, 'address = ' + str(id(str2)))
测试结果-1
str1 = abc address = 2690867975664
str2 = abc address = 2690867975664
测试代码-2
str1 = 'Python'
lst = ['Py', 'thon']
str2 = ''.join(lst)
str3 = 'Py' + 'thon'
print('str1 = ' + str1, 'address = ' + str(id(str1)))
print('str2 = ' + str2, 'address = ' + str(id(str2)))
print('str3 = ' + str3, 'address = ' + str(id(str3)))
测试结果-2
str1 = Python address = 2306053934384
str2 = Python address = 2306059848304
str3 = Python address = 2306053934384
通过以上测试用例,我们可以总结出,在 Python 中,如果给两个变量直接赋值相同的字符串对象,那么 Python 就会启用字符串驻留机制,使得两个变量指向同一字符串对象;对于拼接的字符串,如果使用 join( ) 函数,那么一定会创建一个新的字符串对象,并不会启用字符串驻留机制,而对于 + 拼接的字符串,如果驻留池中存在,那么就会指向驻留池中的字符串对象,并不再创建新的字符串对象。