记录一下基础数据类型的操作补充、编码知识补充、练习部分。
方法补充
补充下基础数据类型有点奇技淫巧的操作。
str
主要有capitalize、swapcase、title、center、find、index等方法。
s1='meSSI'
# 首字母大写,其他小写
print(s1.capitalize()) # Messi
# 大小写翻转
print(s1.swapcase()) # MEssi
# 每个单词首字母大写,空格或数字隔开的都生效
msg='messi ronald herry4kaka'
print(msg.title()) # Messi Ronald Herry4Kaka
# 神奇的center方法,将字符放中间
s1='messi'
print(s1.center(11,'*')) # ***messi***
# find index都可以通过元素找索引,前者找不到不会报错(返回-1),后者找不到就报错
s1='messi'
print(s1.find('m')) # 0
print(s1.find('s')) # 2 找到第一个元素就返回
print(s1.find('y')) # -1
print(s1.index('m')) # 0
print(s1.index('s')) # 2
# print(s1.index('y')) # 报错 ValueError: substring not found
tuple
元祖中,如果只有一个元素,并且没有逗号,那就不是元祖,而是对应数据类型。
# 这三个都不是元祖
t1=(1)
t2=('messi')
t3=([1,2,3])
print(t1,type(t1)) # 1 <class 'int'>
print(t2,type(t2)) # messi <class 'str'>
print(t3,type(t3)) # [1, 2, 3] <class 'list'>
# count计数
t=(1,2,2,2,3,3)
print(t.count(2)) # 3
# index,如果有多个元素,返回第一个元素的索引,下面有两个messi,只返回第一个messi的索引
t=('messi','herry','ronald','messi')
print(t.index('messi')) # 0
list
可以排序和翻转。
# sort排序
li=[1,4,5,6463,32334,55]
# 默认升序
li.sort()
print(li) # [1, 4, 5, 55, 6463, 32334]
# 降序,需要指定
li.sort(reverse=True)
print(li) # [32334, 6463, 55, 5, 4, 1]
# reverse翻转
li=[1,4,5,6463,32334,55]
li.reverse()
print(li) # [55, 32334, 6463, 5, 4, 1]
# 列表可以相加
l1=[1,2,3]
l2=[4,5,6]
print(l1+l2) # [1, 2, 3, 4, 5, 6]
# 列表可以相乘
l1=[1,2,3]
print(l1*3) # [1, 2, 3, 1, 2, 3, 1, 2, 3]
如下,将列表中索引为奇数的元素删除,有多种方法,并且还有坑。
如下方式1和方式2都是比较好理解的。对于方式3,倒着删除是没有问题的,因为删除后面的元素,对下一个要比较的元素没有影响,下一个要比较的元素的索引依然是原来的索引。如果是正向删除,问题就出现了,删除前面元素,后面元素会往前移动,影响了后面元素的索引,原来的索引和元素的对应关系遭到破坏,如果想删除指定的元素将变得不准确。
# 准备列表
l1=[1,2,3,4,5,6,7,8,9,10]
# 方式1
# del l1[1::2]
# print(l1)
# 方式2
# l2=[]
# # for index in range(len(l1)):
# # if index%2==0:l2.append(l1[index])
# # print(l2)
# 方式3 根据索引,倒着删除
for index in range(len(l1)-1,-1,-1):
if index%2==1:l1.pop(index)
print(l1)
# 结果均为[1, 3, 5, 7, 9]
dict
可以使用update更新字典,依然是有则改、无则增的原则。
# update方法
t1={'name':'messi','age':33,'salary':8848}
# 传入一个字典,有则改(age修改了),无则增(增加了hobby)
t1.update({'hobby':'football','age':35})
print(t1) # {'name': 'messi', 'age': 35, 'salary': 8848, 'hobby': 'football'}
# 传入key=value
t1.update(hobby='basketball')
print(t1) # {'name': 'messi', 'age': 35, 'salary': 8848, 'hobby': 'basketball'}
# 传入可以迭代的数据,元祖拆包后,分别添加到key和value
t1.update([(1,'a'),(2,'b'),(3,'c'),(4,'d')])
print(t1) # {'name': 'messi', 'age': 35, 'salary': 8848, 'hobby': 'basketball', 1: 'a', 2: 'b', 3: 'c', 4: 'd'}
# fromkeys,value是共用的,key从可迭代的数据里获取
dic=dict.fromkeys('abc',1)
print(dic) # {'a': 1, 'b': 1, 'c': 1}
# 有坑来了 ,[]是共用的
dic=dict.fromkeys([1,2,3],[])
dic[1].append(666) # value是共用一个列表,其中一个改了value,所有value均更新
print(dic) # {1: [666], 2: [666], 3: [666]}
字典也有要注意的坑,当给字典做遍历时,还有删除字典的操作,就会报错。
# 删除key中含有'k'这个字母的
dic={'k1':1,'k2':2,'k3':3,'name':'clyang'}
# 不能在循环字典进行读的同时,做删除操作,循环一个字典时,如果改变了字典的大小,就会报错
# 报错 RuntimeError: dictionary changed size during iteration
# for k in dic.keys():
# if 'k' in k:
# dic.pop(k,'删除不了')
# print(dic)
# 方式1 dic.keys()强转为列表再操作
dic={'k1':1,'k2':2,'k3':3,'name':'clyang'}
for k in list(dic.keys()):
if 'k' in k:
dic.pop(k)
print(dic) # {'name': 'clyang'}
# 方式2 两步走,先将key临时存起来
dic={'k1':1,'k2':2,'k3':3,'name':'clyang'}
keys=[]
for k in dic.keys():
keys.append(k)
print(keys) # ['k1', 'k2', 'k3', 'name']
for k in keys:
if 'k' in k:
dic.pop(k)
print(dic) # {'name': 'clyang'}
bool
以下几种数据类型,都可以转换为bool型的False。
print(bool(0))
print(bool(''))
print(bool([]))
print(bool(()))
print(bool({}))
print(bool(set()))
print(bool(None))
编码补充
前面学习到,数据在内存中,都是按照unicode编码保存,如果保存到本地磁盘,需要使用utf-8或者gbk来保存。
bytes类型
bytes类型,也是python的一种数据类型,它是非unicode类型,既可以用于网络传输数据,又可以用来保存数据到本地。它对应的方法非常类似str。
如何表示一个bytes类型呢,参考如下代码,包含英文和中文的表示方法。
# 英文的bytes类型,直接写,前面加b
s='messi'
b=b'messi'
print(s,type(s)) # messi <class 'str'>
print(b,type(b)) # b'messi' <class 'bytes'>
# 中文的bytes类型,不能直接写,写了会提示bytes类型只能包含ASCII字符
s='梅西'
# b=b'梅西' # 报错 SyntaxError: bytes can only contain ASCII literal characters.
# 按照utf-8编码,一个中文3个字节
b=s.encode('utf-8')
print(b) # b'xe6xa2x85xe8xa5xbf'
# 使用上面获取的结果,重新写bytes类型
b=b'xe6xa2x85xe8xa5xbf'
print(s,type(s)) # 梅西 <class 'str'>
print(b,type(b)) # b'xe6xa2x85xe8xa5xbf' <class 'bytes'>
bytes类型如何转换成str类型,使用解码方法即可。
# str--->bytes
s='梅西'
b=s.encode('utf-8')
print(b,type(b)) # b'xe6xa2x85xe8xa5xbf' <class 'bytes'>
# bytes--->str 解码
b=b'xe6xa2x85xe8xa5xbf'
s=b.decode('utf-8')
print(s) # 梅西
类型转换
不管是gbk还是utf-8编码的数据,都可以使用decode方法解码成unicode类型,然后可以使用这个通用的类型,做中间桥梁,实现其他类型之间的相互转换。
# gbk--->utf-8
# 获取梅西的gbk编码
# s='梅西'
# b=s.encode('gbk')
# print(b) # b'xc3xb7xcexf7'
# 使用上面获取到的结果
g=b'xc3xb7xcexf7'
# gbk->unicode
s=g.decode('gbk')
print(s) # 梅西
# unicode->utf-8
u=s.encode('utf-8')
print(u) # b'xe6xa2x85xe8xa5xbf'
相关练习
- 判断某个数据是否在在字典的键中
info = {'name': 'clyang', 'age': 28, 'salary': 8848, 'hobby': 'football'}
# 以下两种方法都可以
# print('name' in info)
print('name' in info.keys()) # True
- 看代码说结果
变量指向的是真实的数据,当v1重新赋值ronald,原来v2指向的真实数据还是没变,改的只是v1指向的地址。
v1='messi'
v2=[1,2,3,v1]
v1='ronald'
print(v2) # [1, 2, 3, 'messi']
- 看代码说结果
v1=[1,2,3,4,5,6,7,8,9]
v2={}
for item in v1:
if item<6:
continue
if 'k1' in v2:
v2['k1'].append(item)
else:
v2['k1']=[item]
print(v2) # {'k1': [6, 7, 8, 9]}
- 看代码说结果
v1=[1,2,3,4,5,6,7,8,9]
v2={}
for item in v1:
if item<6:
continue
if 'k1' in v2:
v2['k1'].append(item)
else:
v2['k1']=[item]
print(v2) # {'k1': [6, 7, 8, 9]}
- 深copy练习
前面三个没有问题的,后面的三个容易出问题,需要考虑到缓存机制。
v1=[1,2,3,{'name':'messi','numbers':[1,2,3]},4,5]
v2=copy.deepcopy(v1)
print(v1 is v2) # False
print(v1[0] is v2[0]) # True
print(v1[3] is v2[3]) # False
# 狗血的来了
print(v1[3]['name'] is v2[3]['name']) # True 同一代码块的缓存机制
print(v1[3]['numbers'] is v2[3]['numbers']) # False
print(v1[3]['numbers'][1] is v2[3]['numbers'][1]) # True 同一代码块的缓存机制
- 关于字典的巨坑题
可以看出,li中的dic,指向的是同一个内存地址中的字典数据,每次循环改变的只是字典里的value,li里的所有dic元素都指向同一个内存区域,因此li最后会是如下的结果。
li=[]
dic={}
for i in range(10):
dic['user']=i
li.append(dic)
print(li) # [{'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}]
- 使用python代码,构建如下列表,有多种写法
# 构建出 [['_','_','_'],['_','_','_'],['_','_','_']]
# 方法1
outer=[]
for i in range(3):
inner=[]
for j in range(3):
inner.append('_')
outer.append(inner)
print(outer)
# 方法2 使用列表相乘
outer=[]
for i in range(3):
outer.append(['_']*3)
print(outer)
# 方法3 更简单的写法,在上面基础上继续简化
print([['_']*3]*3)
- 将列表中所有姓"周"的人的信息都删除掉(有坑)
原始写法
li=['周星驰','周润发','周杰伦','吴腾蓝','周到']
i=1
for item in li:
if item.startswith('周'):
# print(item)
print('第{}次删除'.format(i))
print(li)
li.remove(item)
print(li)
i+=1
print('最后结果')
print(li) # ['周润发', '吴腾蓝']
这样写,是有问题的,从以下打印的结果就可以看出来:
1 第一次删除,检查索引为0的数据,是"周星驰",结果删除
2 第二次删除,检查索引为1的数据,结果"周润发"没有删除,它跑到了索引为0的位置
3 第三次删除,检查索引为2的数据,结果"周到"删除了
可以看出后面元素往前移动时,原来的索引和元素的对应关系破坏了,导致删除乱了套,得不到想要的结果。
第1次删除
['周星驰', '周润发', '周杰伦', '吴腾蓝', '周到']
['周润发', '周杰伦', '吴腾蓝', '周到']
第2次删除
['周润发', '周杰伦', '吴腾蓝', '周到']
['周润发', '吴腾蓝', '周到']
第3次删除
['周润发', '吴腾蓝', '周到']
['周润发', '吴腾蓝']
最后结果
['周润发', '吴腾蓝']
修改后写法,可以解决此问题。
li=['周星驰','周润发','周杰伦','吴腾蓝','周到']
# 倒着来删除
for index in range(len(li)-1,-1,-1):
if li[index].strip().startswith('周'):
# 以下都可以
# li.remove(li[index])
li.pop(index)
print(li)
- 车牌区域划分,先给出以下车牌,根据车牌的信息,分析出各省的车牌持有量
车牌数据:cars=['鲁A35325','鲁B45345','鲁C45671','京A55555','湘K26888','湘A12345','闽A88888']
车牌和省份区域的对应关系:locals={'鲁':'山东','京':'北京','湘':'湖南','闽':'福建','黑':'黑龙江','沪':'上海'}
预测输出结果: {'山东':3,'北京':1,'湖南':2,'福建':1}
# 方式1 自己的写法
result={}
for car in cars:
# 切片出省份
province=car[0:1]
# 根据省份名,获取全地点名,暂不考虑获取不到的情况
full_name=locals.get(province)
# 判断结果字典,是否有这个省的数据,有则改,无则增
if full_name in result:
result[full_name]=result[full_name]+1
else:
result[full_name]=1
print(result)
# 方式2 更加简单的写法
result={}
for car in cars:
# 巧用字典的get方法
result[locals[car[0]]]=result.get(locals[car[0]],0)+1
print(result)
第二种方法很巧妙的利用了字典的get方法,我是想不出来这种方法,只能写出第一种暂时。
- 求水仙花数
水仙花数,是一个三位数,水仙花数的值=各位上的数字的三次幂之和 ,如370=3^3+7^3+0^3。
while 1:
input_str=input('请输入一个三位数')
if input_str.upper()=='Q':break
if input_str.isdecimal() and len(input_str)==3:
number=int(input_str)
# 判断
# number_1=int(number/100)
# number_2=int((number-number_1*100)/10)
# number_3=number-number_1*100-number_2*10
number_1=int(input_str[0])
number_2=int(input_str[1])
number_3=int(input_str[2])
# 求和
buf=number_1**3+number_2**3+number_3**3
# 判断是否是水仙花数
if number==buf:
print(number,', 是水仙花数')
else:
print(number,', 不是水仙花数')
else:
print('输入格式有误,请重新输入')
控制台结果。
以上,记录以备后用。
参考博文:
(1)https://www.cnblogs.com/youngchaolin/p/10927325.html#_label4 python编码