不可变的字符串
python中的数据类型分为可变的和不可变的两种,字符串属于不可变的数据类型。
不可变的数据类型可以作为字典的键使用,例如:
my_dict = {'Lily': 68, 'Harry': 98, 'Lucy': 79}
不可变类型的另一个优点就是有助于进行内部消化,从而提高运行效率。例如:使用元组比使用列表的效率更高。
不可变类型的局限就在于无法“就地”更改。例如:
my_str = 'Hello, Dave, this is Hal.'
my_str[0] = 'H'
第二条语句就是无效的,因为它尝试获取在第一条语句中创建的字符串并修改它。结果Python抛出了TypeError异常。
而以下语句是有效的。
my_str = 'hello'
my_str = 'Hello'
因为每条语句都会创建一个新的字符串,并将其分配给my_str变量。
在python中变量不过是个名字,在上面的操作中,实际上是创建了两个不同的字符串给了两个同名的变量,可以通过id()函数来查看变量的内存地址
my_str = 'hello'
print('第一个my_str内存地址:', id(my_str))
my_str = 'Hello'
print('第二个my_str内存地址:', id(my_str))
第一个my_str内存地址: 2332623983408
第二个my_str内存地址: 2332623983344
所以在程序中,后面出现了和前面一样名字的变量时,只要赋值的值是新的就会产生一个新的变量,而当后面赋值的值与前面的同名变量的值一样才会保留旧的变量,因为python中的不可变数据类型不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,就是不可变数据类型引用的地址的值不可改变,改变对象的值,其实是引用了不同的对象。
数据类型转换
只要变量支持某种转换,那么使用该类型的名称就会引起类型转换,其语法如下:
新数据类型(旧数据对象)
当转换合规就会从旧的数据类型转换成新数据类型,但如果转换不存在,python就会报错。
例如:
s = '45'
n = int(s)
x = float(s)
45
45.0
其中,int转换可以接受第二个参数,此参数可以按不同的进制转换为数字 (例如二进制)
n = int('10001', 2)
print(n)
n = int('1f', 16)
print(n)
17
31
字符串运算符(+、=、*、>等)
字符串也能支持一些数字类型的运算符,但实际用途不同。
例如:
dog1_str = 'Rover'
dog2_str = dog1_str
print(dog1_str == dog2_str)
print(dog1_str == 'Rover')
True
True
在这个例子中,第二个语句为dog1_str引用的数据创建了一个别名dog2_str,因为两个变量所引用的是相同的数据,所以第一个结果为True。
print(id(dog1_str))
print(id(dog2_str))
1731897414448
1731897414448
(但如果之后将dog1_str赋值了新的数据,dog2_str仍然引用'Rover')
第二个相等性测试也返回True,因为只要两个字符串的内容相同,就视为他们相等,它们不一定指向内存中相同的数据。
所以,在使用运算符对字符串进行比较的时候是区分大小写的,可以对字符串使用upper()或lower()函数转换成全大写或全小写,这种方式只对包含ASCII字符的字符串有效。
如果对于使用更为强大的Unicode字符集的字符串,则应该使用专门为此设计的casefold()方法进行不区分大小写只比对内容的比对方式较为安全
例如:
def compare_no_case(str1, str2):
return str1.casefold() == str2.casefold()
print(compare_no_case('cat', 'CAT'))
True
运算符语法 | 说明 |
---|---|
name = str | 将字符串赋值给指定变量 |
str1 == str2 | 当str1和str2有相同的内容时返回True,大小写敏感 |
str1 != str2 | 当str1和str2有不同内容时返回True |
str1 < str2 | 当str1按字母表顺序出现在str2前时返回True, 如' abc'<' def'返回True, 'abc'<'aaa'返回False (查看下面关于顺序的说明) |
str1 > str2 | 当str1按字母表顺序出现在str2后时返回True,如'def'>'abc'返回True,' def'>'xyz'返回False |
str1 <= str2 | 当str1按字母表顺序出现在str2前或两者内容相同时返回True |
str1 >= str2 | 当str1按字母表顺序出现在str2后或两者内容相同时返回True |
str1 + str2 | 连接两个字符串,就是将str2的内容粘贴到str1末尾。例如,'Big'+'Deal'结果为'BigDeal' |
str1 * n | 将该字符串连接到自身n次,其中n是一个整数,例如,'Goo’* 3的结果为'GoGooGoo' |
n * str1 | 与str1 * n相同 |
str1 in str2 | 如果字符串str1整体包含在str2中,则返回True |
str1 not in str2 | 如果字符串str1不包含在str2中,则返回True |
str is obj | 如果str和obj指向内存中的同-对象,则返回True。该运算符在将字符串与None或未知类型对象进行比较时很有用 |
str is not obj | 如果str和obj指向内存中的不同对象,则返回True |
Pyth
在字符串的拼接时使用“+”运算符,不会自动在中间添加空格,所以必须手动添加,“ ' ' ”也是字符串类型,例如:
first = 'will'
last = 'Shakespeare'
full_name = first + ' ' + last
print(full_name)
will Shakespeare
还有在创建一个分割线的时候也可以通过运算符来快速完成
divider_str = '-' * 30
print(divider_str)
------------------------------
目前为止,使用乘法运算符来创建是最效率的方式。
注意,不要滥用 is 和 is not 运算符。这两个运算符测试两个值在内存中是否是相同的对象。可以理解为是在比对象的唯一标识符是否相等,而并非比较变量的值。如果单纯的想要比值是否一致应使用(==)运算符。例:
a = [1, 2]
b = [1, 2]
print(id(a))
print(id(b))
print(a is b)
print(a == b)
1929803551168
1929807299776
False
True
索引和切片
对于索引和切片,我更倾向于自己总结的数轴模型
python中切片语法如下表
语法 | 得到的字符串 |
---|---|
string[beg:end] | 从 beg 开始到 end(不包含)的字符串 |
string[:end] | 从头一直到 end(不包含)的字符串 |
string[beg:] | 从 beg 一直到结尾的字符串 |
string[:] | 整个字符串,该操作会复制原字符串 |
string[beg: end: step] | 从 beg 到 end (不包含)的字符串,字符之间的索引间隔为 step |
ad
假设要删除字符串开头和结尾的双引号,则可以
king_str = '"Harry VIII"'
new_str = king_str[1:-1]
print(new_str)
Harry VIII
从字符串中每3个字符取一个
a_str = 'AbcDefGhiJklMnoP'
print(a_str[::3])
ADGJMP
由切片的规则,我们得出下面这些有趣的结论:
- 如果 beg 和 end 均为正索,则 end-beg 给出切片的最大长度
- 要获取包含原字符串前 N个字符的字符串,使用 string[:N]
- 要获取包含原字符串最后N个字符的字符串,使用string[-N:]。
- 要创建字符串的完整副本,使用 string[:]。
单字符函数
python中有两个函数是为长度为1的字符串设计的。这两个函数是弹字符函数,虽然它们的操作的对象也是字符串类型。
ord(str) #返回字符的数字编码
chr(n) #将ASCII/Unicode编码转换成一个字符
ord 函数接受一个字符串参数,但是如果字符串长度大于 1,则会引发TypeError异常。可以使用此函数返回对应字符的ASCII或Unicode编码。例如下面的示例显示字母A的ASCI码为十进制 65。
print(ord('A'))
65
用join函数构建字符串
前面我们说过,可以用加法运算符来拼接一个新的字符串。
例如:我们欲想要得到“Big Bad John”,我们可以
a_str = 'Big '
a_str = a_str + 'Bad '
a_str = a_str + 'john'
print(a_str)
他们都使用了相同的变量名,并为他们分配了一个新字符串,以下语句同样有效
a_str = 'Big '
a_str += 'Bad '
a_str += 'John'
print(a_str)
Big Bad John
这种构建字符串的方法对于少量对象的情况是没啥问题,但当需要拼接的散碎字符串数量庞大的时候,这个看起来“简洁”的例子则会使python一次又一次的在内存中创建全新的字符串。
一种更好的方法就是使用join方法
new_str.join(list)
此方法会将所有的字符串一次性全部拼接成一个新字符串,在运行时比上面的传统案例快速很多。在代码量上也会减少很多,例如:
def print_nice(a_lst):
s = ''
for item in a_lst:
s += item + ', '
if len(s) > 0:
s = s[:-2]
print(s)
print_nice(['John', 'Paul', 'George', 'Ringo'])
def print_nice(a_lst):
print(', '.join(a_lst))
print_nice(['John', 'Paul', 'George', 'Ringo'])
John, Paul, George, Ringo