Python自学第八天——字符串

作为新手自学Python的第八天,技术低微,希望可以通过这种方式督促自己学习。

个人学习环境:python3.9,PyCharm 2021.3.2 (Community Edition)

———————————————————————————————————————————

在Python中字符串是基本数据类型,是一个不可变的字符序列(目前所学不可变序列有:元组、字符串)

1、字符串驻留机制

1.1 字符串的创建

第一种 单引号' '
第二种 双引号" "
第三种 三引号''' '''
a = 'Python'
b = "Python"
c = '''Python'''
# 三引号是可换行字符串,字符串不赋值给变量,可以当做注释使用
# 具体三单引号与三双引号可查看此篇文档http://t.csdn.cn/sCOvz

1.2 字符串驻留机制

字符串驻留是一种在内存中仅保存一份相同且不可变字符串的方法。 Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量。

a = 'Python'
b = "Python"
c = '''Python'''
print(a, id(a))
print(b, id(b))
print(c, id(c))
"""
结果为:
Python 2462425264432
Python 2462425264432
Python 2462425264432
"""

1.3 驻留机制的几种情况(交互模式)

字符串的长度为0或1

符合标识符的字符串

字符串只在编译时进行驻留,而非运行时

[-5,256]之间的整数数字

# 这里代码需要使用cmd进行运行,Pycharm运行都是True,是因为Pycharm对字符串进行了优化处理
# 字符串长度为0或1
 s1 = ''
>>> s2 = ''
>>> s1 is s2
True
>>> s1 = '%'
>>> s2 = '%'
>>> s1 is s2
True
# 符合标识符的字符串
>>> s1 = 'abc%'
>>> s2 = 'abc%'
>>> s1 is s2
False
>>> s1 == s2
True
>>> id(s1)
2318579417904
>>> id(s2)
2318579417968
>>> s1 = 'abcd'
>>> s2 = 'abcd'
>>> s1 is s2
True
>>> s1 == s2
True
>>> id(s1)
2318579418032
>>> id(s2)
2318579418032
# 字符串只在编译时进行驻留,而非运行时
>>> a = 'abc'
>>> b = 'ab'+'c'
>>> c = ''.join(['ab','c'])
>>> a is b
True
>>> a is c
False
>>> c
'abc'
>>> type(c)

>>> a
'abc'
>>> type(a)
   #a、b在程序编译时就已经是'abc',而c是在运行时才通过join方法转为'abc'
# [-5,256]之间的整数数字   
# 为什么是[-5,256]这个区间,可以参考Python中神秘的-5到256 - Jerry Jho的文章 - 知乎 https://zhuanlan.zhihu.com/p/33907983
>>> a = -5
>>> b = -5
>>> a is b
True
>>> a = -6
>>> b = -6
>>> a is b
False

标识符的基本使用规则:

在python里,标识符有字母、数字、下划线组成。

在python中,所有标识符可以包括英文、数字以及下划线(_),但不能以数字开头。

python中的标识符是区分大小写的。

sys中的intern方法强制2个字符串指向同一个对象

# 依旧使用cmd运行
>>> import sys
>>> s1 = 'abc%'
>>> s2 = 'abc%'
>>> s1 is s2
False
>>> s1 = sys.intern(s2)
>>> s1 is s2
True

1.4 字符串驻留机制的优缺点

当需要值相同的字符串时可以直接从池中拿来使用,避免了频繁的创建和销毁,提升效率和节约内存

拼接字符串和修改字符串会比较影响性能

在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join()是先计算出所有字符中的长度,然后再拷贝,其中只new一次对象,效率比“+”高

2、字符串的常用操作

2.1 查询操作

方法名称 说明
index() 查找子串第一次出现的位置,如果不存在,则报错
rindex() 查找子串最后一次出现的位置,如果不存在,则报错
find() 查找子串第一次出现的位置,如果不存在,则返回-1
rfind() 查找子串最后一次出现的位置,如果不存在,则返回-1
s = 'hello,hello'
print(s.index('lo'))    # 3
print(s.find('lo'))     # 3
print(s.rindex('lo'))   # 9
print(s.rfind('lo'))    # 9

2.2 大小写转换操作

方法名称 说明
upper() 字符串中所有字符转为大写
lower() 字符串中所有字符转为小写
swapcase() 字符串中所有大小写互换,大写转为小写,小写转为大写
capitalize() 第一个字符转为大写,其余字符转为小写
title() 每个单词的第一个字符转为大写,每个单词剩余字符转为小写

转换之后会产生一个新的字符串

2.3 内容对齐操作

方法名称 说明
center() 居中对齐,第1个参数指定宽度,第2个参数指定填充符
ljust() 左对齐,第1个参数指定宽度,第2个参数指定填充符
rjust() 右对齐,第1个参数指定宽度,第2个参数指定填充符
zfill() 右对齐,左边用0填充

对于center()、ljust()、rjust()来说,第2个参数可选,默认为空格。如果设置的宽度小于实际宽度则返回原字符串

对于zfill(),只接收一个参数用于指定字符串的宽度,如果制定的宽度小于等于字符串的长度,则返回字符串本身

# 居中
s = 'hello,Python'
print(s.center(20, '*'))
​
# 左对齐
print(s.ljust(20, '*'))
print(s.ljust(10))
print(s.ljust(20))
​
# 右对齐
print(s.rjust(20, '*'))
print(s.rjust(20))
print(s.rjust(10))
​
# zfill()
print(s.zfill(20))
print(s.zfill(10))
print('-8910'.zfill(8))
"""
结果为:
****hello,Python****
hello,Python********
hello,Python
hello,Python        
********hello,Python
        hello,Python
hello,Python
00000000hello,Python
hello,Python
-0008910
"""

2.4 分割操作

方法名称 说明
split() 从字符串的左边开始分割,默认的分割字符为空格,返回的值都是一个列表
以通过参数sep指定分割字符串
通过参数maxsplit指定分割字符串时的最大分割次数,经过最大次分割之后,剩余的字串单独为一部分
rsplit() 从字符串的右边开始分割,默认的分割字符为空格,返回的值都是一个列表
以通过参数sep指定分割字符串
通过参数maxsplit指定分割字符串时的最大分割次数,经过最大次分割之后,剩余的字串单独为一部分
s = 'hello world Python'
lst = s.split()
print(lst)
s1 = 'hello|world|python'
print(s1.split(sep='|'))
print(s1.split(sep='|', maxsplit=1))
"""
结果为:
['hello', 'world', 'Python']
['hello', 'world', 'python']
['hello', 'world|python']
"""
# rsplit()从右侧开始分割
# rsplit()从右侧开始分割
print(s.rsplit())
print(s1.rsplit('|'))
print(s1.rsplit(sep='|', maxsplit=1))
"""
结果为:
['hello', 'world', 'Python']
['hello', 'world', 'python']
['hello|world', 'python']
"""

2.5 字符串判断操作

方法名称 说明
isidentifier() 判断指定的字符串是不是合法的标识符
isspace() 判断指定的字符串是否全部由空白字符组成(回车、换行,水平制表符)
isalpha() 判断指定的字符串是否全部由字母组成
isdecimal() 判断指定字符串是否全部由十进制的数字组成
isnumeric() 判断指定的字符串是否全部由数字组成
isalnum() 判断指定字符串是否全部由字母和数字组成
# 判断字符串是否合法
s = 'hello,Python'
print('1.', s.isidentifier())   # 1.False
print('2.', 'hello'.isidentifier())     # 2.True
print('3.', '张三_'.isidentifier())   # 3.True
print('4.', '张三_123'.isidentifier())    # 4.True
# 判断字符串是否全由空白字符组成
print('5.', '\t'.isspace())     # 5.True
# 判断字符串是否全由字母组成
print('6.', 'abc'.isalpha())    # 6.True
print('7.', '张三'.isalpha())     # 7.True
print('8.', '张三1'.isalpha())    # 8.False
# 判断字符串是否全由十进制数字组成
print('9.', '123'.isdecimal())     # 9.True
print('10.', '123四'.isdecimal())    # 10.False
print('11.', 'ⅢⅢⅢ'.isdecimal())    # 11.False
# 判断字符串是否全由数字组成
print('12.', '123'.isnumeric())     # 12.True
print('13.', '123四'.isnumeric())    # 13.True
print('14.', 'ⅢⅢⅢ'.isnumeric())     # 14.True
# 判断字符串是否全由字母和数字组成
print('15.', 'abc1'.isalnum())      # 15.True
print('16.', '张三123'.isalnum())     # 16.True
print('17.', 'abc!'.isalnum())      # 17.False

2.6 字符串操作的其他方法

功能 方法名称 说明
字符串替换 replace() 第一个参数指定被替换的子串,第二个参数指定替换子串的字符串,返回替换后得到的字符串
字符串合并 join() 将列表或元组中的字符串合并成一个字符串

replace()方法中,替换前的字符串不发生变化,调用该方法时可以通过第3个参数指定最大替换次数

s = 'hello,Python'
print(s.replace('Python', 'Java'))
"""
结果为:
hello,Java
"""
s1 = 'hello,Python,Python,Python'
print(s1.replace('Python', 'Java', 2))
"""
结果为:
hello,Java,Java,Python
"""
s = 'hello,Python'
print(s.replace('Python', 'Java'))
"""
结果为:
hello,Java
"""
s1 = 'hello,Python,Python,Python'
print(s1.replace('Python', 'Java', 2))
"""
结果为:
hello,Java,Java,Python
"""
lst = ['hello', 'java', 'python']
print('|'.join(lst))
print(''.join(lst))
"""
结果为:
hello|java|python
hellojavapython
"""
t = ('hello', 'java', 'python')
print(''.join(t))
"""
结果为:
hellojavapython
"""
print('*'.join('Python'))
"""
结果为:
P*y*t*h*o*n
"""

2.7 比较操作

运算符:>,>=,<,<=,==,!=

规则:先比较两个字符串中第一个字符,如果相等则继续比较下一个字符,依次进行比较,直到两个字符串中的字符不相等后,其比较结果就是两个字符串的比较结果,两个字符串的所有后续字符将不再被比较

原理:两字符比较时,比较的是ordinal value(原始值),调用内置函数ord可以得到指定字符的ordinal value。与内置函数ord对应的是内置函数chr,调用内置函数chr时指定的ordinal value可以得到其对应的字符

print('apple' > 'app')  # True
print('apple' > 'banana')   # False
print(ord('a'), ord('b'))   # 97 98
print(chr(97),chr(98))      # a b

== 与 is 的区别

== 比较的是value

is 比较的是id是否相等

2.8 切片操作

字符串是不可变类型:不具备增、删、改等操作

切片将产生新的对象

s = 'hello,Python'
s1 = s[:5]   # 没有指定起始位置,从0开始
s2 = s[6:]   # 没有指定结束位置,一直到最后元素
s3 = '!'
newstr = s1 + s3 + s2

print(s1)
print(s2)
print(newstr)

# 完整写法[start:stop:step]
print(s[1:5:1])
print(s[::2])
print(s[::-1])  # 默认从最后一个元素开始
print(s[-6::1])     # 索引从-6开始,一直到最后

2.9 格式化字符串

第一种:%做占位符

第二种:{}做占位符(format方法格式化)

第三种:f-string(python3.6引入了一种新的字符串格式化方式:f-string格式化字符串。值得注意的是,f-string就是在format格式化的基础之上做了一些变动,核心使用思想和format一样)

name = '张三'
age = 20
print('我叫%s,今年%d岁' % (name, age))

print('我的名字叫{0},今年{1}岁'.format(name, age))

# f-string
print(f'我叫{name},今年{age}岁')

设置宽度精度

print('%d' % 99)
print('%10d' % 99)  # 10表示宽度

print('%f' % 3.1415926)
print('%.3f' % 3.1415926)   # .3表示小数点后三位

print('%10.3f' % 3.1415926)     # 总宽度为10,小数点后3位

print('{0}'.format(3.1415926))
print('{0:.3}'.format(3.1415926))   # .3表示一共是3位数
print('{0:.3f}'.format(3.1415926))  # .3f表示3位小数
print('{0:10.3f}'.format(3.1415926))    # 宽度是10,3位小数

3、字符串的编码转换

3.1 为什么要编码转换

数据传输所用,在传输中字符串转为二进制,传输后二进制转为字符串

3.2 编码与解码的方式

编码:将字符串转换为二进制数据(bytes)

解码:将bytes类型的数据转换成字符串类型

# 编码
s = '天涯共此时'
print(s.encode(encoding='GBK'))     # GBK编码格式中一个中文占两个字节
"""
结果为:
b'\xcc\xec\xd1\xc4\xb9\xb2\xb4\xcb\xca\xb1'
# b表示二进制
"""
print(s.encode(encoding='UTF-8'))   # UTF-8编码格式中一个中文占三个字节
"""
结果为:
b'\xe5\xa4\xa9\xe6\xb6\xaf\xe5\x85\xb1\xe6\xad\xa4\xe6\x97\xb6'
"""

# 解码
# byte代表一个二进制数据(字节类型的数据)
byte = s.encode(encoding='GBK')     # 编码
print(byte.decode(encoding='GBK'))  # 解码
# 编码解码的编码格式必须选择同一类型
byte = s.encode(encoding='UTF-8')
print(byte.decode(encoding='UTF-8'))

你可能感兴趣的:(Python自学,python)