Python学习笔记
课程笔记参考B站视频:
Python全栈开发教程。
第九站 一串连一串
本章重点介绍关于字符串的一些常用操作。
1. 字符串的驻留机制
字符串是Python中的一个基本数据类型,是一个不可变的字符序列。
字符串驻留机制 说的是Python仅保存一份相同且不可变字符串的方法。定义字符串时,不同的值会被存放在字符串的驻留池中,此时Python的驻留机制对相同的字符串只保留一份拷贝,后续再创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量。
下面是代码示例:
'''
演示字符串的驻留机制
'''
st1 = 'python'
st2 = "python"
st3 = '''python'''
print(type(st1), id(st1), st1)
print(type(st2), id(st2), st2)
print(type(st3), id(st3), st3)
<class 'str'> 2178301622960 python
<class 'str'> 2178301622960 python
<class 'str'> 2178301622960 python
而在交互模式下,字符串的驻留机制则会变的更加严格,只有以下情况才会触发驻留机制:
- 字符串的长度为0或1时。
- 符合标识符的字符串(含有字母、数字、下划线的字符串)。
- 字符串只在编译时进行驻留,而非运行时。
- [- 5,256]之间的整数数字。
注:交互模式指的是打开Python的命令行程序(打开windows命令行,输入Python可快速进入交互模式,但是我是通过Pycharm自动安装的Python,实测这个方法不是很好用)。 注:标识符的定义可以参考 “python合法标识符的定义规则”。 注:PyCharm对字符串进行了优化处理,使用Pycharm看不出上述现象。
情况一:字符串长度为0或1
情况二:字符串不是标识符,不触发驻留机制
情况三:字符串只在编译时驻留
若想在交互模式下也开启字符串的驻留机制,可以导入sys 中的intern 方法强制2个字符串指向同一个对象(注意在调用语法上已经默认了两个字符串的内容必须相同):
情况四:演示强制驻留
讲了这么多,那Python中为什么要设置这个字符串驻留机制呢?即,字符串驻留机制的优点为:
当需要值相同的字符串时,可以直接从字符串池里拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是会比较影响性能的。
所以,在需要进行 字符串拼接时建议使用str 类型的join 方法, 而非 + ,因为join() 方法是先计算出所有字符中的长度,然后再拷贝,只给对象分配一次内存,效率要比" + "高。
2. 字符串的常用操作
1. 字符串的查询操作
功能 | 方法名称 | 作用 |
---|
查询方法 | .index() | 查找子串substr第一次出现的位置,若不存在则抛出ValueError | .rindex() | 查找子串substr最后一次出现的位置,若不存在则抛出ValueError | .find() | 查找子串substr第一次出现的位置,若不存在时则返回-1 | .rfind() | 查找子串substr最后一次出现的位置,若不存在则返回-1 |
如上表,由于字符串与列表的组成结构非常相似,所以字符串中也有.index()方法,不同的是,字符串还有更多的查询方法。
下面是代码示例:
st1 = 'hello,hello'
print('-----------使用index()方法------------')
print('lo的索引:', st1.index('lo',4))
print('lo的索引:', st1.rindex('lo',0,5))
print('-----------使用find()方法-------------')
print('lo的索引:', st1.find('lo',5))
print('lo的索引:', st1.rfind('lo',0,5))
print('k的索引:', st1.find('k'))
-----------使用index()方法------------
lo的索引: 9
lo的索引: 3
-----------使用find()方法-------------
lo的索引: 9
lo的索引: 3
k的索引: -1
杨淑娟老师说为了避免error,建议使用find而非index。(但我觉得使用index不是可以更快的找到error?)
2. 大小写转换操作
功能 | 方法名称 | 作用 |
---|
大小写转换 | .upper() | 把字符串中所有字符都转成大写字母 | .lower() | 把字符串中所有字符都转成小写字母 | .casefold() | 与.lower()功能相同,但更加强大(可以转换德语等) | .swapcase() | 把字符串中所有字母的大小写全部反转 | .capitalize() | 对于整个字符串,第一个字符大写,其余全部小写 | .title() | 对于字符串中的每个单词,第一个字符大写,其余小写 |
下面是代码示例:
'''
演示字符串的大小写转换
'''
st1 = 'hello, Python, Gro?'
print('upper: ', st1.upper())
print('lower: ', st1.lower())
print('casefold: ', st1.casefold())
print('swapcase: ', st1.swapcase())
print('capitalize: ', st1.capitalize())
print('title: ', st1.title())
print('原字符串没变:', st1)
upper: HELLO, PYTHON, GROSS
lower: hello, python, gro?
casefold: hello, python, gross
swapcase: HELLO, pYTHON, gROSS
capitalize: Hello, python, gro?
title: Hello, Python, Gro?
原字符串没变: hello, Python, Gro?
注:所有的大小写转换操作都是新生成了一个字符串,不会对原来的字符串产生影响。
3. 内容对齐操作
功能 | 方法名称 | 作用 |
---|
内容对齐 | .center() | 居中对齐,第1个参数指定宽度,第2个参数指定填充符。 第2个参数可选,默认空格。 如果设置宽度小于实际宽度,则返回原字符串。 | .ljust() | 左对齐,第1个参数指定宽度,第2个参数指定填充符。 第2个参数可选,默认空格。 如果设置宽度小于实际宽度,则返回原字符串。 | .rjust() | 右对齐,第1个参数指定宽度,第2个参数指定填充符。 第2个参数可选,默认是空格。 如果设置宽度小于实际宽度,则返回原字符串 | .zfill() | 右对齐,左边用0填充,该方法只接收一个参数,用于指定字符串的宽度。 如果指定的宽度小于实际宽度,则返回原字符串。 对于数字串,会自动检测符号位。 |
下面是代码示例:
st1 = 'hello,Python'
print('-----------演示center----------')
print('center:', st1.center(19,'*'))
print('center:', st1.center(0,'*'))
print('-----------演示ljust-----------')
print('ljust:', st1.ljust(15,'/'))
print('ljust:', st1.ljust(-1,'/'))
print('-----------演示rjust-----------')
print('rjust:', st1.rjust(15,'/'))
print('rjust:', st1.ljust(-10,'/'))
print('-----------演示zfill-----------')
print('zfill:', st1.zfill(15))
print('zfill:', st1.zfill(-10))
print('zfill:', '-12.3'.zfill(-10))
print('zfill:', '-12.3'.zfill(15))
-----------演示center----------
center: ****hello,Python***
center: hello,Python
-----------演示ljust-----------
ljust: hello,Python///
ljust: hello,Python
-----------演示rjust-----------
rjust: ///hello,Python
rjust: hello,Python
-----------演示zfill-----------
zfill: 000hello,Python
zfill: hello,Python
zfill: -12.3
zfill: -000000000012.3
注意到,.zfill() 方法对于数字串是敏感的。
4. 字符串的劈分
功能 | 方法名称 | 作用 |
---|
字符串的劈分 | .split() | 从字符串的左边开始劈分,返回一个列表。 1. 关键字参数sep指定劈分符,默认劈分字符是空格字符串。 2. 关键字参数maxsplit指定最大劈分次数。超过maxsplit后,剩余字符串将单独做为一部分。 | .rsplit() | 从字符串的右边开始劈分,其余参数与.split()相同 |
注意关键字参数与之前的位置参数不同的地方在于:只要声明了关键字,关键词参数的顺序随便放,但如果没有写关键字,就必须按照默认顺序提供参数;并且,也不建议只声明一部分关键字参数。 注:上面这段话没有写的太清楚,可以先参考“Python的位置参数、默认参数、关键字参数、可变参数之间的区别”,后面学完函数再补齐。
下面是代码示例:
s = 'hello*world*Pyhton'
print('----------演示split()----------')
print('原字符串:', s)
print('split: ', s.split())
print('split: ', s.split(sep='*',maxsplit=100))
print('split: ', s.split('*',1))
print('----------演示rsplit()---------')
print('原字符串:', s)
print('rsplit: ', s.rsplit('*'))
print('rsplit: ', s.rsplit(maxsplit=1, sep='*'))
print('rsplit: ', s.rsplit('*',100))
----------演示split()----------
原字符串: hello*world*Pyhton
split: ['hello*world*Pyhton']
split: ['hello', 'world', 'Pyhton']
split: ['hello', 'world*Pyhton']
----------演示rsplit()---------
原字符串: hello*world*Pyhton
rsplit: ['hello', 'world', 'Pyhton']
rsplit: ['hello*world', 'Pyhton']
rsplit: ['hello', 'world', 'Pyhton']
5. 字符串判断
功能 | 方法名称 | 作用 |
---|
字符串的判断 | .isidentifier() | 判断字符串是否为合法的标识符 | .isspace() | 判断字符串是否全部由空白字符组成(回车、换行,水平制表符) | .isalpha() | 判断字符串是否全部由字母组成 | .isdecimal() | 判断字符串是否全部由十进制的数字组成 | .isnumeric() | 判断字符串是否全部由数字组成 | .isalnum() | 判断字符串是否全部由字母和数字组成 |
下面是代码示例:
print('----------演示isidentifier()-----------')
print('hello,python: ', 'hello,python'.isidentifier())
print('张三: ', '张三'.isidentifier())
print('123: ', '123'.isidentifier())
print('----------演示isspace()-----------')
print('\\t:', '\t'.isidentifier())
print('123:', '123'.isidentifier())
print('----------演示isalpha()-----------')
print('abc:', 'abc'.isalpha())
print('ab1:', '张三'.isalpha())
print('----------演示isdecimal()-----------')
print('123:', '123'.isdecimal())
print('1011:', '1011'.isdecimal())
print('----------演示isnumeric()-----------')
print('123四:', '123四'.isnumeric())
print('ⅠⅡⅢ:', 'ⅠⅡⅢ'.isnumeric())
print('----------演示isalnum()-----------')
print('123四:', '123四'.isalnum())
print('张三:', '张三'.isalnum())
print('张三_:', '张三_'.isalnum())
----------演示isidentifier()-----------
hello,python: False
张三: True
123: False
----------演示isspace()-----------
\t: False
123: False
----------演示isalpha()-----------
abc: True
ab1: True
----------演示isdecimal()-----------
123: True
1011: True
----------演示isnumeric()-----------
123四: True
ⅠⅡⅢ: True
----------演示isalnum()-----------
123四: True
张三: True
张三_: False
6. 替换与合并
功能 | 方法名称 | 作用 |
---|
字符串的替换 | .replace() | 第1个参数指定被替换的子串,必填。 第2个参数指定替换子串的字符串,必填。 第3个参数指定最大替换次数,可选。 | 字符串的合并 | .join() | 将列表或元组中的字符串合并成一个字符串。 |
下面是代码示例:
print('-----------演示replace----------')
s = 'hello,Python,Python,Python'
print(s.replace('Python',"C++"))
print(s.replace('Python',"C++",2))
print('-----------演示join-------------')
lst = ['hello', 'C++', '!']
tup = ('hello', '打工人', '!')
print(','.join(lst))
print(','.join(tup))
print(','.join('Python'))
-----------演示replace----------
hello,C++,C++,C++
hello,C++,C++,Python
-----------演示join-------------
hello,C++,!
hello,打工人,!
P,y,t,h,o,n
3. 字符串的比较
字符串比较的过程就是 逐字符的比较 其ordinal value(原始值),其实也就是ASCII码值。值得注意的有:
字符串的比较运算符包括:>, >=, <, <=, ==, != 内置函数ord() 可以得到指定字符的原始值。 内置函数chr() 可以得到指定原始值对应的字符。
下面是代码示例:
print('apple>app: ', 'apple'>'app')
print('a的原始值: ', ord('a'))
print('97的对应字符: ', chr(0x61))
apple>app: True
a的原始值: 97
97的对应字符: a
4. 字符串的切片操作
字符串是不可变类型,本身不具备增、删、改等操作。字符串切片的方法与列表切片基本一致(列表可以增删改),切片操作将产生新的对象。
下面是代码示例:
s = 'python,hello'
s1 = s[:6]
s2 = s[7:]
s3 = s2 + ',' + s1
print('s: ', id(s), s)
print('s1: ', id(s1), s1)
print('s2: ', id(s2), s2)
print('s3: ', id(s3), s3)
s: 2161532467504 python,hello
s1: 2161532849840 python
s2: 2161532849904 hello
s3: 2161532849968 hello,python
5. 格式化字符串
当某一大段文本中只有少量的文本需要修改,此时再使用字符串拼接的方法就会浪费大量的内存,所以格式化字符串应运而生。格式化字符串就是按照一定方式输出的字符串,主要有三种方式:
- % 作为占位符。%s 表示字符串;%i 或 %d 表示整数;%f 表示浮点数。
- { } 作为占位符。花括号里面的值表示索引,若只有一个数据,可以不写索引。
- f-string。Python3中还定义了f字符串方法,可以直接将变量名写进花括号里面。
下面是代码示例:
name1 = '张三'
name2 = '李四'
height = 175.535
print('----------%做占位符-----------')
print('%s的身高为%.2fcm。' % (name1, height))
print('----------{}做占位符----------')
print('{0}的身高为{1}cm,{2}的身高也为{1}cm。'.format(name1, height, name2))
print('----------f-string----------')
print(f'{name1}的身高为{height}cm,{name2}的身高也为{height}cm。')
print('-----------输出精度的演示----------')
print('%1d' % 99)
print('%.3f' % 3.1415926)
print('%10.3f' % 3.1415926)
print('{0:.3}'.format(3.1415926))
print('{:.3f}'.format(3.1415926))
print('{:10.3f}'.format(3.1415926))
----------%做占位符-----------
张三的身高为175.53cm。
----------{}做占位符----------
张三的身高为175.535cm,李四的身高也为175.535cm。
----------f-string----------
张三的身高为175.535cm,李四的身高也为175.535cm。
-----------输出精度的演示----------
99
3.142
3.142
3.14
3.142
3.142
6. 字符串的编码转换
由于字符串在内存中以Unicode的形式存储,若要传输到其他计算机,就需要编码成byte字节(二进制数据)进行传输,接收端再将byte字节解码成相应的字符串类型进行显示。这种场景下就需要考虑字符串的编码转换问题。
下面是代码示例:
s_t = '去码头整点薯条'
byte1 = s_t.encode(encoding='gbk')
byte2 = s_t.encode(encoding='utf-8')
print('GBK编码:', byte1)
print('UTF-8编码:', byte2)
s1_r = byte1.decode(encoding='GBK')
s2_r = byte2.decode(encoding='UTF-8')
print('GBK解码:', s1_r)
print('UTF-8解码:', s2_r)
GBK编码: b'\xc8\xa5\xc2\xeb\xcd\xb7\xd5\xfb\xb5\xe3\xca\xed\xcc\xf5'
UTF-8编码: b'\xe5\x8e\xbb\xe7\xa0\x81\xe5\xa4\xb4\xe6\x95\xb4\xe7\x82\xb9\xe8\x96\xaf\xe6\x9d\xa1'
GBK解码: 去码头整点薯条
UTF-8解码: 去码头整点薯条
7. 本章作业
1. 统计字符串中出现指定字符的次数
下面是代码示例:
str1 = 'kjlbgvscdaohcsdc;l5354'
ser_letter = input('请输入要搜索的字符:')
fin_num = 0
for i in str1:
if i==ser_letter:
fin_num += 1
print(ser_letter,'在', str1, '中出现了', fin_num, '次')
请输入要搜索的字符:s
s 在 kjlbgvscdaohcsdc;l5354 中出现了 2 次
2. 格式化输出商品的名称和单价
由于没能获取到高清图片,所以直接看示例代码体会具体要做的事情吧。
下面是代码示例:
lst=[['01','电风扇','美的',500],
['02','洗衣机','TCL',1000],
['03','微波炉','老板',400]]
print('编号\t\t名称\t\t\t晶牌\t\t单价')
for item in lst:
for i in item:
print(i, end='\t\t')
print()
print(''.center(32,'-'))
for item in lst:
item[0] = '00' + item[0]
item[3] = '¥{:.2f}'.format(item[3])
print('编号\t\t\t名称\t\t\t晶牌\t\t单价')
for item in lst:
for i in item:
print(i, end='\t\t')
print()
编号 名称 晶牌 单价
01 电风扇 美的 500
02 洗衣机 TCL 1000
03 微波炉 老板 400
--------------------------------
编号 名称 晶牌 单价
0001 电风扇 美的 ¥500.00
0002 洗衣机 TCL ¥1000.00
0003 微波炉 老板 ¥400.00
|