• 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'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编码

  • 相关阅读:
    Android屏幕适配
    设计模式学习心得
    C语言中的作用域、链接属性与存储属性
    二级指针删除单向链表
    C++编程风格
    python中index、slice与slice assignment用法
    lua_pcall与lua_call之间的区别
    lua-C++ userdata使用
    lua中调用C++函数
    C++中为什么有时要使用extern "C"
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/12600577.html
Copyright © 2020-2023  润新知