zoukankan      html  css  js  c++  java
  • 流畅的python,Fluent Python 第四章笔记

    4.1字符问题:

    字符的标识即码位,是一串数字,再unicdoe中以4-6个16进制数标识。(其实码位就时字符了,就好比我的名字是小明,小明就是我。再py3,unicode直接输出文字,在py2里print输出unicode也时具体文字)

    字符的具体表述取决于所用的编码。编码是在码位和字节序列之间转换时使用的算法。

    把码位转换成字节序列的过程叫做编码;把字节序列转换成码位的过程叫做解码。

    简单理解,编码时给机器用的,解码后是给人用的。

    4.2字节该要

    In [687]: b'xc3xa9'.decode('U8')                                                                                      
    Out[687]: 'é'
    
    In [688]: cafe = bytes('café', encoding='utf8')                                                                         
    
    In [689]: cafe                                                                                                          
    Out[689]: b'cafxc3xa9'
    
    In [690]: cafe[0]                                                                                                       
    Out[690]: 99
    
    In [691]: cafe[-1]                                                                                                      
    Out[691]: 169
    
    In [692]: cafe[-1:]                                                                                                     
    Out[692]: b'xa9'
    
    In [693]: cafe = bytearray(cafe)                                                                                        
    
    In [694]: cafe                                                                                                          
    Out[694]: bytearray(b'cafxc3xa9')
    
    In [695]: cafe[0]                                                                                                       
    Out[695]: 99
    
    In [696]: cafe[-1]                                                                                                      
    Out[696]: 169
    
    In [697]: cafe[-1:]                                                                                                     
    Out[697]: bytearray(b'xa9')
    
    In [698]: '12345'[2:3] == '12345'[2]                                                                                    
    Out[698]: True
    

     通过代码可以看到,bytes与bytesarray的各个元素都是介于0-255(含)【两个16进制数字的区间,二进制111111111,8个1最大就是255】之间的整数。

    二进制序列的切片始终是同以类型的二进制序列,包括长度位1的切片。

    可迭代对象的切片中,从上面可以看出,只有str可以做到,取值于切片是一样的。

    另外的取值是取值,切片出来的一个相同类型的序列,里面包含这个取值的元素。

    好比s[i] 是取出迭代中的i值,s[i :i+1]取出的是s[i]

    从输出可以看到,字节序列只有三种不同的方式显示

    1、可以打印的ASCII范围内的字节,使用ASCII字符自身

    2、制表符、换行符、回车符和,就是 \

    3、就是x啦啦,啦啦为两个16进制数字

    字节序列可以用很多字符串的方法,除了那些判断字符串属性的以外,可以简单的认为也是一个字符串,只不过是一个比较特殊的二进制字符串。

    In [753]: bytes.fromhex('314bcea9')                                                                                     
    Out[753]: b'1Kxcexa9'
    

     这是bytes特有的方法,可以从字符串直接转换为字节序列,31于4b因为刚好对应ASCII的1于K所以直接输出了1于K,当时卡住我老半天。

    In [246]: bytes([12,80,56,255])                                                                    
    Out[246]: b'x0cP8xff'

    bytes后面可以直接跟一个可迭代的数字(0,256),里面的每个元素能直接按照asci码对应的表中取参数,有的直接输出,没有的按照x已16进制形式输出字节序列。

    如何创建一个字节序列对象呢。

    1、最直接

    In [752]: '!love你,
    '.encode()                                                                                         
    Out[752]: b'!lovexe4xbdxa0,
    '
    

     上面可以看出来,标点符号,英文字母都输出来了,就是中文被输出了另外的。

    构建bytes或bytearray实例还可以调用各自的构造方法,传入下述参数。

    1、一个str对象和一个encoding关键字参数

    2、一个可迭代对象,提供0-255之间的数值(难道就我前面写的fromhex)

    3、一个实现了缓冲协议的对象(如bytes、bytearray、memoryview、array.array);此时把源对象中的字节序列复制到新建的二进制序列中。

    (啥叫缓冲协议对象,我查不到资料,郁闷。)书中代码上一下

    In [754]: numbers = array.array('h',[-2,-1,0,1,2])                                                                      
    
    In [755]: octets = bytes(numbers)                                                                                       
    
    In [756]: octets                                                                                                        
    Out[756]: b'xfexffxffxffx00x00x01x00x02x00'
    
    In [757]:  
    

     不知道这样又有什么意思?而且我试过bytes后面就算不同的0-255之内的数字也可以输出。

    In [761]: bytes([1,2,3,4,5,233])                                                                                        
    Out[761]: b'x01x02x03x04x05xe9'
    
    In [762]:  
    

     后面讲了结构体于内存视图

    struct于meneryview,struct是用来操作二进制数据的,没咋看懂,就不上代码,也不写了。

    4.3基本的编解码器

    Python自带100多种解码器,很多。

    常用的utf-8可以写成utf8,U8

    unicode的字符除了utf-8 utf-16可以全部找到对应的字节次序,另外的都不全,再decode编码的时候,如果碰到自己字符集没有的字符,默认设置就会报错。

    4.4了解编码问题

    如果你不用utf-8去decode遇到自己没有的字符集就会报错。

    In [762]: s = 'abs我cd'                                                                                                 

    In [763]: s.encode(encoding='adcii')                                                                                    
    ---------------------------------------------------------------------------
    LookupError                               Traceback (most recent call last)
    <ipython-input-763-c481354da0b9> in <module>
    ----> 1 s.encode(encoding='adcii')

    LookupError: unknown encoding: adcii

    In [764]: s.encode(encoding='ascii')                                                                                    
    ---------------------------------------------------------------------------
    UnicodeEncodeError                        Traceback (most recent call last)
    <ipython-input-764-8fa11c3441f2> in <module>
    ----> 1 s.encode(encoding='ascii')

    UnicodeEncodeError: 'ascii' codec can't encode character 'u6211' in position 3: ordinal not in range(128)

    In [765]: s.encode(encoding='ascii',errors='ignore')                                                                    
    Out[765]: b'abscd'

    In [766]: s.encode(encoding='ascii',errors='replace')                                                                   
    Out[766]: b'abs?cd'

    In [767]: s.encode(encoding='ascii',errors='xmlcharrefreplace')                                                         
    Out[767]: b'abs&#25105;cd'

    In [768]:         

     有三个参数可以选择,最后一个参数有意思,网页上面尽然又显示出来这个我字了

    In [767]: s.encode(encoding='ascii',errors='xmlcharrefreplace')                                                         
    Out[767]: b'abs我cd'
    

     书中还说,error的参数是可扩张的。

    当然decode也一样了

    In [770]: s                                                                                                             
    Out[770]: 'abs我cd'
    
    In [771]: s.encode('U8').decode('ascii',errors='ignore')                                                                
    Out[771]: 'abscd'
    
    In [772]: s.encode('U8').decode('ascii',errors='replace)                                                                
      File "<ipython-input-772-ed017d19dba1>", line 1
        s.encode('U8').decode('ascii',errors='replace)
                                                      ^
    SyntaxError: EOL while scanning string literal
    
    
    In [773]:      
    

     用用utf-8时建议写replace,因为会给一个默认的替代字符,这笔调过这个字好多了

    4.4.4如何找出字节序列的编码

    用chardet.detect

    In [774]: string = '我是大叔阿瓜'                                                                                       
    
    In [775]: import chardet                                                                                                
    
    In [776]: gg = string.encode('gbk')                                                                                     
    
    In [777]: uu = string.encode()                                                                                          
    
    In [778]: chardet.detect(gg)                                                                                            
    Out[778]: {'encoding': None, 'confidence': 0.0, 'language': None}
    
    In [779]: chardet.detect(uu)                                                                                            
    Out[779]: {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
    
    In [780]: chardet.detect('师傅登革热特哥时代风范厄尔人'.encode('gbk'))                                                  
    Out[780]: {'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
    
    In [781]:  
    

     字符数据越多越准确。

    4.5处理文本文件。

    在用open处理文本文件的时候,encoding不要使用系统默认的,容易出问题。

    然后就是尽量使用linux系统电脑,因为系统里面所有的编码,解码都是基于utf-8的,

    这样可以字节序列于字符编码,解码时候的错误。

    我们处理文档默认的编码为:

    In [810]: locale.getpreferredencoding()                                                                                 
    Out[810]: 'UTF-8'
    

    4.6为了正确比较而规范化Unicode字符串(感觉用到的机会不大)

    后面基本都是基于国外文字,德文,拉丁文相关的unicdoe处理,我稍微看了下。就不写了。

  • 相关阅读:
    dpkg 被中断,您必须手工运行 sudo dpkg –configure -a 解决此问题
    运行wpscan报错Could not find 'nokogiri' (~> 1.8.0)
    理解:jar和war的区别
    AcWing3494. 国际象棋(状压DP)
    AcWing3422. 左孩子右兄弟(树形DP)
    python命名空间
    mysql日志大量报错“original commit timestamp is more recent than the immediate commit timestamp”
    python模块导入
    Centos-Docker镜像制作
    python面向对象之封装
  • 原文地址:https://www.cnblogs.com/sidianok/p/12057756.html
Copyright © 2011-2022 走看看