Python学习-基础数据类型补充操作、bytes类型

记录一下基础数据类型的操作补充、编码知识补充、练习部分。

方法补充

补充下基础数据类型有点奇技淫巧的操作。

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'\xe6\xa2\x85\xe8\xa5\xbf'

# 使用上面获取的结果,重新写bytes类型
b=b'\xe6\xa2\x85\xe8\xa5\xbf'
print(s,type(s)) # 梅西 <class 'str'>
print(b,type(b)) # b'\xe6\xa2\x85\xe8\xa5\xbf' <class 'bytes'>

bytes类型如何转换成str类型,使用解码方法即可。

# str--->bytes
s='梅西'
b=s.encode('utf-8')
print(b,type(b)) # b'\xe6\xa2\x85\xe8\xa5\xbf' <class 'bytes'>

# bytes--->str 解码
b=b'\xe6\xa2\x85\xe8\xa5\xbf'
s=b.decode('utf-8')
print(s) # 梅西 

类型转换

不管是gbk还是utf-8编码的数据,都可以使用decode方法解码成unicode类型,然后可以使用这个通用的类型,做中间桥梁,实现其他类型之间的相互转换。

# gbk--->utf-8

# 获取梅西的gbk编码
# s='梅西'
# b=s.encode('gbk')
# print(b) # b'\xc3\xb7\xce\xf7'

# 使用上面获取到的结果
g=b'\xc3\xb7\xce\xf7'
# gbk->unicode
s=g.decode('gbk')
print(s) # 梅西
# unicode->utf-8
u=s.encode('utf-8')
print(u) # b'\xe6\xa2\x85\xe8\xa5\xbf'

相关练习

  • 判断某个数据是否在在字典的键中
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=33+73+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编码

猜你喜欢

转载自www.cnblogs.com/youngchaolin/p/12600577.html