对象
在Python中,万物皆对象,每一个对象,都是独立的、独一无二的个体
每1个对象都有自己的唯一标识(简称id,类似于人的身份证),可以通过 id 函数获取对象的id
如果2个对象的id相同,说明它们其实是同1个对象
可变类型,不可变类型
list 是可变类型,int,float,bool,str是不可变类型,这里说的可变、不可变指的是对象,并不是指变量,变量是肯定可以变的。
方法
方法是一种需要通过对象来调用的特殊函数(function) 方法的使用格式是:对象.方法名(参数)
list 常用方法
1. 查询index
-
s.index(x) 查询元素 x 在 s 中的最小索引(从左往右搜索) 如果元素 x 不在 s 中,会报错(ValueError)
-
s.index(x, i, j) 在 [i, j) 范围内搜索(包头不包尾)
-
s.index(x, i),在 [i, len(s)) 范围内搜索(即从索引 i 一直搜到末尾)
2. 查询 - count
s.count(x) 统计 s 中有多少个元素 x
3.添加 - append
添加 - s.append(x):添加元素 x 到 s 的尾部,注意一点就是append操作,新生成的对象和旧的对象其实还是一个对象
s.append(x) 等价于 s[len(s):] = [x]
4.插入 - insert
s.insert(i, x):将元素x插入到索引为i的位置,首先i的正常合理范围是[-len(s), len(s) - 1],如果i < -len(s),代表往头部插入, 如果i > len(s) - 1,代表往尾部插入,跟s.append(x)效果是一样的- s.insert(i, x) 等价于 s[i:i] = [x]
5.添加 - extend
s.extend(t):将可迭代对象t中的所有元素添加到尾部
s = [55]
# extend 可以一次性将另一个列表里的元素全部追加进来
s.extend([44, 33])
# extend 后面只要是“可迭代对象”就行,range(20, 0, -10) 会生成 20 和 10
s.extend(range(20, 0, -10))
# [55, 44, 33, 20, 10]
print(s)
注意append和extend的区别
注意的是append要求是只能加单个,不论你是数字,还是list都当成一个整体加进去,而extend加的是可迭代对象,比方说1数字不是可迭代对象,就不能用extend,要写也只能写成extend([1]),他是把可迭代对象的对象一个一个捞出来放到原对象中
s1 = [55, 44, 33]
# extend 会把列表 [22, 11] 拆开,把里面的元素逐个加进去
s1.extend([22, 11])
# [55, 44, 33, 22, 11]
print(s1)
s2 = s1
# append 会把列表 [22, 11] 当成“一个独立的对象”,整个塞到末尾
s2.append([22, 11])
# [55, 44, 33, [22, 11]] (形成了嵌套列表)
print(s2)
6.删除 - pop
s.pop(i):删除并返回索引为i的元素,如果不写的话就是删除尾部元素。i必须要合理,如果空列表,调这个方法要报错(IndexError: pop from empty list),越界也会报IndexError错误。\
s.pop()如果用切片可以用s[len(s) - 1:] = [] 或者 s[-1:] = [] \
如果s是空列表,p s.pop() 会报错(IndexError),s[len(s) - 1:] = []、s[-1:] = [] 并不会报错
s.pop(i) 等价于 s[i:i + 1] = [],如果i越界了,s.pop(i) 会报错(IndexError),s[i:i + 1] = [] 并不会报错
7.删除 - remove
s.remove(x),删除1个元素x(从左往右搜索),如果元素x不在列表中,会报错(ValueError)
s = [55, 44, 33, 44, 44]
# 从左往右找,删除了第一个遇到的 44,后面的保留
s.remove(44)
# [55, 33, 44, 44]
print(s)
# ValueError: 66 is not in list (如果要删除的元素不存在,程序会直接报错)
s.remove(66)
8.del删除
使用关键字del实现删除功能(del是delete的简写)
s = [55, 44, 33, 22, 11]
# 1. 删除单个指定索引的元素
del s[0]
# [44, 33, 22, 11]
print(s)
# 2. 结合切片批量删除(这里步长为2,即删掉索引为 0 和 2 的元素 44 和 22)
del s[::2]
# [33, 11]
print(s)
# 3. 注意:如果像下面这样删除单个不存在的越界索引,会直接报错
# IndexError: list assignment index out of range
# del s[100]
# 4. 但是:如果使用切片的形式删除越界范围,则不会报错(只是相当于什么都没删)
del s[100:]
del s[i:j] 等价于 s[i:j] = []
s = [55, 44, 33, 22, 11]
# 把切片范围内的元素赋值为空列表,就相当于把它们删除了
# 这里的效果完全等同于执行 del s[1:4]
s[1:4] = []
# 最终剩下的结果
# [55, 11]
print(s)
几个区别
- del s[:] 和 del s
del s[:] 是切片删除,它的作用是:清空列表里的所有元素。此时变量 s 依然存在,只是变成了一个空列表 []。
del s 是删除整个变量,它的作用是:把变量 s 这个名字从内存中彻底抹除。
s = [55, 44, 33, 22, 11]
# 1. del s[:]
del s[:]
print(s) # []
del s
# 因为变量 s 已经被删除了,所以再试图打印它会直接报错:
# NameError: name 's' is not defined (变量名没定义)
print(s)
# 3. 既然前面的 s 已经被抹除了,你可以随时重新定义它指向别的东西
s = 55
print(s) # 55
2.s[:] = [] 和 s = [] 的区别
s[:] = []这种写法,s1 从头到尾都指向着同一个列表对象(原地清空)。
s = [] 最后重新指向了 1 个新的空列表对象(和原来的对象不是同一个对象,他们的id不一样)。\
s1 = [55, 44, 33, 22, 11]
print(id(s1)) # 假设地址是:2224932534848
# 把原列表里的内容全部掏空
s1[:] = []
# 因为还是原来的那个列表,所以内存地址完全没变!
print(id(s1)) # 依然是:2224932534848
print(s1) # []
s2 = [55, 44, 33, 22, 11]
print(id(s2)) # 假设地址是:2385144540480
# 这不是清空,而是直接让 s2 绑定到一个全新创建的空列表上
s2 = []
# 因为换了一个新列表,所以内存地址彻底改变了!
print(id(s2)) # 变成了新地址:2387353328384
print(s2) # []
9.删除clear
s.clear(),删除所有元素,等价于del s[:]
str 常用方法
1.查询index和rindex
s.index(x, i, j) 从左往右查找,查找在[i, j)范围内搜索,如果有多个,获取的是最小索引,如果是一个都没有,则会报错(ValueError).
s.rindex(x, i, j) 从右往左查找,查找在[i, j)范围内搜索,如果有多个,获取的是最小索引,如果是一个都没有,则会报错(ValueError).
上面的两个方法如果i,j都不写的话,则就是查找整个字符串
2. 查询 - find和rfind
和上面的index,rindex方法类似,差别在于index,rindex如果找不到指定的子串,程序会直接抛出报错(ValueError),导致程序崩溃中断,而find和rfind找不到会返回 -1
3. 查询 - count 方法
s.count(x) 统计 s 中有多少个子串 x(核心注意:子串之间是不重叠计算的)
s.count(x, i) 在 [i, len(s)) 范围内统计
s.count(x, i, j) 在 [i, j) 范围内统计(包头不包尾)
4. 查询 - endswith
s.endswith(x, i, j)
p 在[i, j)范围内查看
4. 查询 - startswith
用于检查字符串是否以特定的子串开头。
s.startswith(x):查看s是否以子串x开头。s.startswith(x, i):在[i, len(s))范围内查看。s.startswith(x, i, j):在[i, j)范围内查看(包头不包尾)
s = 'MJ666MJ666'
# 基础检查
print(s.startswith('MJ')) # True
print(s.startswith('66')) # False
# 指定范围检查
print(s.startswith('MJ', 5)) # True (从索引 5 开始,即后半段 'MJ666')
print(s.startswith('MJ', 2, 8)) # False (在 '666MJ6' 范围内查找,并非以 'MJ' 开头)
# 特殊情况
print(s.startswith('')) # True (任何字符串都默认以空字符串开头)
print(s.startswith(s)) # True (自身总是以自身开头)
5. 大小写处理
s.upper():返回s的全大写形式。s.lower():返回s的全小写形式。s.swapcase():大小写反转(大写变小写,小写变大写)。s.title():标题化,即每个单词的首字符变大写。s.capitalize():首字母大写,其余所有字符强制变小写。
# 全大写与全小写
s1 = 'jack'
print(s1.upper()) # JACK
s2 = 'JACK'
print(s2.lower()) # jack
# 大小写反转
s3 = 'Hello World'
print(s3.swapcase()) # hELLO wORLD
# 首字母大写 (title vs capitalize)
s4 = 'my name is jack'
print(s4.title()) # My Name Is Jack (每个单词首字母都大写了)
print(s4.capitalize()) # My name is jack (仅整个字符串的第一个字母大写)
# capitalize 会将后面原本的大写强行转为小写
s5 = 'hELLO WorLD'
print(s5.capitalize()) # Hello world
判断大小写
s.isupper():判断s是否为全大写。s.islower():判断s是否为全小写。
print('JACK'.isupper()) # True
print('jAcK'.isupper()) # False
print('jack'.islower()) # True
print('jAcK'.islower()) # False
6. 字符串格式化
用于将变量动态插入到字符串中。从 Python 3.6 开始,推荐使用更简便的 f-string 语法。
- 传统用法:
s.format() - 现代用法:在字符串前加
f或F前缀。
name = 'MJ'
age = 18
# 现代推荐写法 (f-string)
print(f'My name is {name}, age is {age}')
# 输出: My name is MJ, age is 18
# 传统写法 (.format)
print('My name is {}, age is {}'.format(name, age))
# 输出: My name is MJ, age is 18
7.空格与特定字符剔除:strip 系列
用于剥离字符串边缘的冗余字符。
剔除空格(默认行为)
s.strip():删除左右两端的空格字符。s.lstrip():只删除左边的空格(left)。s.rstrip():只删除右边的空格(right)。
s = ' 1 2 '
# 拼接 '0' 是为了在终端里能直观看到边缘空格被删除的情况
print(f'0{s}0') # 0 1 2 0 (原状)
print(f'0{s.strip()}0') # 01 20 (左右两端的空格都被删除了,中间的保留)
print(f'0{s.lstrip()}0') # 01 2 0 (只删了左边)
print(f'0{s.rstrip()}0') # 0 1 20 (只删了右边)
剔除指定字符集
s.strip(x):删除左右两端的任意属于x集合内的字符。 (注意:这里的x是一个字符集合,剔除时不讲究顺序,只要边缘字符在这个集合里就会被删,直到遇到一个不在集合里的字符为止。)
s_url = 'www.520it.com'
# 只要边缘的字符属于 '5', 'm', 'w', '.', 'c', 't' 中的任何一个,就会被剔除掉
# 左侧:'w', '.', '5' 被剔除,停在 '2'
# 右侧:'m' 被剔除,停在 'o'(因为 'o' 不在集合里)
print(s_url.strip('5mw.ct')) # 结果:20it.co
# 单侧处理同理
print(s_url.lstrip('5mw.ct')) # 结果:20it.com
print(s_url.rstrip('5mw.ct')) # 结果:www.520it.co
8.拼接:join
用于将一个“可迭代对象”中的多个字符串,使用指定的分隔符连接成一个新的字符串。
s.join(x):x是一个可迭代对象(例如列表、元组等)。- 注意:
x中的所有元素必须都是字符串 (str) 类型,否则会报错。s将作为拼接时的分隔符。
s1 = '+=+'
data = ['red', 'blue', 'green']
s2 = s1.join(data)
print(s1, s2, sep='\n')
# 输出:
# +=+
# red+=+blue+=+green
# 常用的快速拼接写法
print('+'.join(['1', '2', '3']))
# 输出: 1+2+3
9.切割:split
用于将一个字符串按照指定的分隔符拆分成多个子串,并以列表 (list) 的形式返回结果。
s.split(x):以x作为分隔符将s切割出若干个子串。s.split(x, k):k是最大切割次数。当k为负数时,表示不限制切割次数(这是默认行为)。
s = '192.168.20.48'
# 默认全部切割
print(s.split('.')) # ['192', '168', '20', '48']
# 以普通数字字符作为分隔符,分隔符本身会被消耗掉
print(s.split('2')) # ['19', '.168.', '0.48']
print(s.split('8')) # ['192.16', '.20.4', '']
# 限制最大切割次数 k
for i in range(5):
print(i, s.split('.', i))
# 0 ['192.168.20.48'] (切0次,原样包裹在一个列表里返回)
# 1 ['192', '168.20.48'] (切1次,分成两块)
# 2 ['192', '168', '20.48']
# 3 ['192', '168', '20', '48']
# 4 ['192', '168', '20', '48'] (最多只能切3次,传4也没影响了)
# 负数 k 表示不限制次数
print(s.split('.', -2)) # ['192', '168', '20', '48']
特殊切割场景说明
- 如果不传分隔符,默认以所有连续的空白字符(空格、换行、制表符等)为分隔符。
- 不能传入空字符串
''作为分隔符,否则会引发ValueError报错。 - 如果想把字符串中的“每一个字符”都单独切开,不要用
split,直接使用list()转换即可。
# 没有传入分隔符,且原字符串没有空白字符,因此整个作为一个元素返回
print('mj666'.split()) # ['mj666']
print('mj666'.split('66')) # ['mj', '6']
print('mj666'.split('8')) # ['mj666'] (找不到指定的分隔符,原样返回)
# 报错:分隔符不能为空!
# print('mj666'.split('')) # ValueError: empty separator
# 正确的“逐字符打散”姿势:使用 list()
print(list('mj666')) # ['m', 'j', '6', '6', '6']
10.补零填充:zfill
主要用于数字字符串的格式化对齐操作(例如生成固定位数的流水号)。
s.zfill(x):用字符0填充到s的左边,直到字符串的总长度达到x。- 智能处理符号:如果字符串以
+或-开头,0会被智能地填充在符号和数字之间。
s1 = '45'
s2 = s1.zfill(5)
print(s1, s2) # 45 00045
# 智能识别正负号
print('+45'.zfill(5)) # +0045
print('-45'.zfill(5)) # -0045
# 如果原长度已经达到或超过 x,则不会做任何事,原样返回
print('12345'.zfill(3)) # 12345
# 实际应用对比:生成固定位数的序列号
# 方式1:传统 % 格式化
for i in range(5):
print('%03d' % i)
# 方式2:使用 zfill (需要先将数字转为 str)
for i in range(5):
print(str(i).zfill(3))
# 上述两种方式输出结果完全一致:
# 000
# 001
# 002
# 003
# 004
11. 替换:replace
用于将字符串中的特定子串替换为新的子串。
s.replace(x, y):将所有的子串x替换为字符串y。 (技巧:当y为空串''时,实际上就相当于删除了所有的子串x) 。s.replace(x, y, k):k是最大替换次数。当k为负数时,不限制替换次数(这是默认行为)。
s1 = '192.168.1.20'
# 全局替换所有匹配项
s2 = s1.replace('.', '_')
print(s1, s2, sep='\n')
# 192.168.1.20
# 192_168_1_20
# 限制替换次数(只替换前两次遇到的 '.')
print(s1.replace('.', '_', 2))
# 192_168_1.20
# 常规替换其他子串
print('mj666'.replace('666', '168')) # mj168
# 特殊技巧:替换为空串相当于"删除"操作
print('www.00700.com'.replace('0', '')) # www.7.com
# 偏门现象:如果被替换项是空串,它会在每个字符的间隙都插入新字符
print('mj666'.replace('', '_')) # _m_j_6_6_6_
12.str的常用方法 - 删除
删除前缀
s.removeprefix(x),删除前缀 x,如果 s 中存在前缀 x,底层逻辑等价于切片操作:s[len(x):]
删除后缀
s.removesuffix(x),删除后缀 x,如果 s 中存在后缀 x,底层逻辑等价于切片操作:s[:-len(x)]
s1 = 'www.520it.com'
# 正常删除确实存在的前缀
s2 = s1.removeprefix('www.')
print(s1, s2, sep='\n')
# www.520it.com
# 520it.com
# 尝试删除一个不是前缀的子串('520it' 在中间)
# 结果:什么都不会删,原样返回
print(s1.removeprefix('520it'))
# www.520it.com
# 等价的切片写法展示(原理演示)
print(s1[len('www.'):])
# 520it.com
s1 = 'www.520it.com'
# 正常删除确实存在的后缀
s2 = s1.removesuffix('.com')
print(s1, s2, sep='\n')
# www.520it.com
# www.520it
# 尝试删除一个不是后缀的子串
# 结果:同样什么都不会删,原样返回
print(s1.removesuffix('520it'))
# www.520it.com
# 等价的切片写法展示(原理演示)
print(s1[:-len('.com')])
# www.520it