python3操作数据

字符串:用于存储文本数据

字节和字节数组:用于存储二进制数据

Python3中的字符串是Unicode,不是字节数组,而Python2需要区分普通的以字节为单位的字符串以及Unicode字符串

\u+4个十六进制的数字:获取Unicode256个基本多语言平面中指定某一特定字符                                                                        \U + 8个十六进制的数字:获取更多的比特位来存储那些位于更高平面的字符

\N{name}引用某一字符,name为该字符的标准名称

unicodedata模块的两个函数:lookup()--接受不区分大小写的标准名称,返回一个Unicode字符;那么()--接受一个Unicode字符,返回大写形式的名称

# _*_ coding: utf-8_*_
import unicodedata
def unicode_test(value):
	name = unicodedata.name(value)
	values = unicodedata.lookup(name)
	print('value="%s", name="%s", values="%s"' % (value,name,values))
unicode_test('A')
unicode_test('$')
unicode_test('\u00a2')
unicode_test('\u2603')	#当缺失对应字符的图片时,会以站位符的形式来显示(用dingbat字体)
unicode_test('\u00E9')
print(unicodedata.lookup('LATIN SMALL LETTER E WITH ACUTE'))
print('\u00e9')
print('\N{LATIN SMALL LETTER E WITH ACUTE}')
print(len('$'))
print(len('\U0001f47b'))		#len()可以计算字符串中Unicode字符的个数,而不是字节数



D:\MyPython>python test2.py
value="A", name="LATIN CAPITAL LETTER A", values="A"
value="$", name="DOLLAR SIGN", values="$"
value="¢", name="CENT SIGN", values="¢"
value="?", name="SNOWMAN", values="?"
value="é", name="LATIN SMALL LETTER E WITH ACUTE", values="é"
é
é
é
1
1

使用UTF-8编码和解码

当与外界进行数据交互时则需要完成两件事:1.将字符串编码为字节;2.将字节解码为字符串

utf_8动态编码:为ascii字符分配1字节;为拉丁语系的语言分配2字节;为其他的位于基本多语言平面的字符分配3字节;为剩下的字符集分配4字节;

编码方式:

编码 说明 'ascii' 经典的7比特ascii编码 'utf-8' 最常用的以8比特为单位的变长编码 'latin-1'  也被称为ISO 8859-1编码 'cp-1252'  Windowss常用编码 'unicode-escape'  Python中Unicode的转义文本格式\uxxxx或者\Uxxxxxxxx

snowman = '\u2603'
print(len(snowman))
ds = snowman.encode('utf-8')
print(len(ds))
print(ds)

D:\MyPython>python test2.py

1

3

b'\xe2\x98\x83'

不以相同的方式进行编码会出错,encode()函数可以接受额外的第二个参数来避免错误,默认值是'strict'

# _*_ coding: utf-8_*_
snowman = '\u2603'
print(snowman.encode('ascii','ignore'))				#抛弃无法编码的字符
print(snowman.encode('ascii','replace'))			#将无法编码的字符替换成?
print(snowman.encode('ascii','backslashreplace'))	#Unicode转义符序列的可打印版
print(snowman.encode('ascii','xmlcharrefreplace'))	#用于创建网页中使用的字符实体串

D:\MyPython>python test2.py

b''

b'?'

b'\\u2603'

b'☃'

解码

如果解码方式不一致,可能出现报错或者解码的结果不一样

# _*_ coding: utf-8_*_
snowman = '\u2603'
print(snowman)
snowman = snowman.encode('utf-8')
print(snowman.decode('utf-8'))	
print(snowman.decode('ascii'))
print(snowman.decode('latin-1'))
				
D:\MyPython>python test2.py
?
?
Traceback (most recent call last):
  File "test2.py", line 6, in <module>
    print(snowman.decode('ascii'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)

格式化

使用%的旧式格式化

转换类型

字符串 %d 十进制整数 %x 十六进制整数 %o 八进制整数 %f 十进制浮点数 %e 以科学计数法表示的浮点数 %g 十进制或科学计数法表示的浮点数 %% 文本值%本身

# _*_ coding: utf-8_*_
print('%s' % 42)
print('%o' % 42)
print('%f' % 42.03)
print('%e' % 42.03)
print('%g' % 42.03)
print('%g' % 42.033333333333)
n = 42
f = 7.03
s = 'string cheese'
print('%d %f %s' % (n,f,s))		#默认宽度格式化
print('%10d %10f %10s' % (n,f,s))	#为每个设置最小域宽为10个字符,右对齐,左侧不够用空格填充
print('%-10d %-10f %-10s' % (n,f,s))	#为每个设置最小域宽为10个字符,左对齐,右侧不够用空格填充
print('%10.4d %10.4f %10.4s' % (n,f,s))	#浮点数的精度限制在小数点后4位
print('%*.*d %*.*f %*.*s' % (10,4,n,10,4,f,10,4,s))	#为每个设置最小域宽为10个字符,右对齐,左侧不够用空格填充



D:\MyPython>python test2.py
42
52
42.030000
4.203000e+01
42.03
42.0333
42 7.030000 string cheese
        42   7.030000 string cheese
42         7.030000   string cheese
      0042     7.0300       stri
      0042     7.0300       stri

使用{}和format的新格式化

# _*_ coding: utf-8_*_

n = 42
f = 7.03
s = 'string cheese'
print('{} {} {}'.format(n,f,s))
print('{2} {0} {1}'.format(f,s,n))	#指定插入的顺序
print('{n} {f} {s}'.format(n=42,f=7.03,s='string cheese'))
d = {'n':42, 'f':7.03, 's':'string cheese'}
print('{0[n]} {0[f]} {0[s]} {1}'.format(d,'other'))	#{0}代表整个字典,{1}代表后面的字符串’other‘
print('{0:d} {1:f} {2:s}'.format(n,f,s))
print('{n:d} {f:f} {s:s}'.format(n=42,f=7.03,s='string cheese'))
print('{0:10d} {1:10f} {2:10s}'.format(n,f,s))
print('{0:>10d} {1:>10f} {2:>10s}'.format(n,f,s))	#右对齐
print('{0:<10d} {1:<10f} {2:<10s}'.format(n,f,s))	#左对齐
print('{0:^10d} {1:^10f} {2:^10s}'.format(n,f,s))	#居中对齐
print('{0:>10d} {1:>10.4f} {2:>10.4s}'.format(n,f,s))	#右对齐, 无法对整数设置精度
print('{0:!^20s}'.format('Big sale')) 	#填充字符,把它放在	:之后


D:\MyPython>python test2.py
42 7.03 string cheese
42 7.03 string cheese
42 7.03 string cheese
42 7.03 string cheese other
42 7.030000 string cheese
42 7.030000 string cheese
        42   7.030000 string cheese
        42   7.030000 string cheese
42         7.030000   string cheese
    42      7.030000  string cheese
        42     7.0300       stri
!!!!!!Big sale!!!!!!

使用正则表达式匹配

对于复杂的匹配,先对模式编译加快匹配速度:

youpattern = re.compile('You')

result = youpattern.match('Young Frankenstein')

search()返回第一次成功匹配,如果存在的话

findall()返回所有不重叠的匹配,如果存在的话

split()根据pattern进行切片分段,返回这些片段组成的列表

sub()匹配的pattern改成replacement

# _*_ coding: utf-8_*_

import re
source = 'Young Frankenstein'
m =re.match('You', source)
if m:
	print(m.group())	#输出匹配到的对象
m = re.match('Frank', source)	#match()只能检测以模式串作为开头的源字符串,但search()可以检测任何位置的匹配
if m:
	print(m.group())	#没有输出
m = re.search('Frank', source)
if m:
	print(m.group())
m = re.match('.*Frank', source)	#.代表任何单一字符,*代表一个它之前的字符, .*代表任何多个字符(包括0个)
if m:
	print(m.group())
m = re.findall('n', source)
print(m,'Found',len(m),'matches')
m = re.split('n', source)
print(m)
m = re.sub('n','?',source)
print(m)



D:\MyPython>python test2.py
You
Frank
Young Frank
['n', 'n', 'n', 'n'] Found 4 matches
['You', 'g Fra', 'ke', 'stei', '']
You?g Fra?ke?stei?

.代表任意除\n外的字符

*表示任意多个字符(包括0个)

?表示可选字符(0个或1个)

   匹配

\d  一个数字字符

\D  一个非数字字符

\w  一个字母或数字字符

\W  一个非字符非数字字符

\s  空白符

\S  非空白符

\b  单词边界

\B  非单词边界

Python的string模块的printable字符串包含100个可打印的ascii字符

# _*_ coding: utf-8_*_

import string
import re 
printable =string.printable
print(len(printable))
print(printable[0:50])
print(printable[50:])
print(re.findall('\d', printable))	#数字
print(re.findall('\w', printable))	#数字,字母,下划线
print(re.findall('\s', printable))	#空格符
x = 'abc' + '-/*' + '\u00ea' + '\u0115'
print(re.findall('\w', x))		#\d不仅仅适用于ascii字符,还可以匹配Unicode的数字字符


D:\MyPython>python test2.py
100
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN
OPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_']
[' ', '\t', '\n', '\r', '\x0b', '\x0c']
['a', 'b', 'c', 'ê', '?']

模式标识符

模式匹配 abc 文本值abc (expr) expr expr1|expr2 expr1或者expr2 . 除\n外的任何字符 ^ 开头 $ 结尾 prev? 0或者1 prev* 0或多,尽可能多匹配 prev*? 0或多,尽可能少匹配 prev+ 1或多,尽可能多匹配 prev+? 1或多,尽可能少匹配 prev{m} m个连续 prev{m,n} m到n个连续,尽可能多匹配 prev{m,n}? m到n个连续,尽可能少匹配 [abc] a或b或c [^abc] 非(a或b或c) prev(?=next) 如果后面为next,返回prev prev(?!next) 如果后面非next,返回prev (?<=prev)next 如果前面为prev,返回next (?<!prev)next 如果前面非prev,返回next

# _*_ coding: utf-8_*_

import string
import re 
source = 'I wish I may,I wish I might have a dish of fish'
print(re.findall('\bfish', source))	#匹配任何以fish开头的单词,但匹配失败
#\b在字符串中表示退格,但在正则表达式中表示一个单词的开头位置,上面产生与
#转义符产生冲突,在模式串前添加r,起到表明为正则表达式,从而禁用字符串转义符
print(re.findall(r'\bfish', source))


D:\MyPython>python test2.py
[]
['fish']

模式:定义匹配的输出

group()返回所有的匹配,如果用括号将模块包裹,groups()可以得到包含这些匹配的元组,

?(P<name>expr)的模式会匹配expr,并将匹配的结果存储到名为name的组中

import string
import re 
source = 'I wish I may,I wish I might have a dish of fish'
m = re.search(r'(. dish\b).*(\bfish)', source)
print(m.group())
print(m.groups())
m = re.search(r'(?P<DISH>. dish\b).*(?P<FISH>\bfish)', source)
print(m.group())
print(m.groups())
print(m.group('DISH'))
print(m.group('FISH'))


D:\MyPython>python test2.py
a dish of fish
('a dish', 'fish')
a dish of fish
('a dish', 'fish')
a dish
fish

字节是不可变的,像字节数据组成的元组

字节数组是可变的,像字节数据组成的列表

# _*_ coding: utf-8_*_
blist = [1,2,3,255]
the_bytes = bytes(blist)
print(the_bytes)
the_byte_array = bytearray(blist)
print(the_byte_array)
the_byte_array[1] = 127	#bytearray类可变性
print(the_byte_array)	
the_bytes[1] = 127	#bytes类不可变性


D:\MyPython>python test2.py
b'\x01\x02\x03\xff'
bytearray(b'\x01\x02\x03\xff')
bytearray(b'\x01\x7f\x03\xff')
Traceback (most recent call last):
  File "test2.py", line 10, in <module>
    the_bytes[1] = 127
TypeError: 'bytes' object does not support item assignment

打印bytes或bytearray数据时,python会以\xxx的形式表示不可打印的字符,以asscii字符的形式表示可打印的字符

使用struct转换二进制数据

什么是大端法和小端法?

在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中的最小地址。

例如,假设一个类型为int的变量x的地址为0x100,即&x的值为0x100。那么x的4个字节将被存储在 存储器的0x100,0x101,0x102和0x103的位置。

字节序即为多字节对象存储在内存中的字节顺序,有两种不同的存储方案:大端法和小端法。现代的处理器大多为双端法,大小端都支持,可以配置称大端法或者小端法。

大端法

最高有效字节在最前面的方式称为大端法,例如假设变量x类型为int型,位于地址0x100的地方,其16进制值为0x12345678,地址范围为0x100到0x103字节。

对于大端法的机器来说:

0x100

0x101

0x102

0x103

12

34

56

78

由上图可见,地址从左向右增长,x的最高有效字节12在最前面存储。这正好和我们平时书写习惯一致,先书写最高有效字节,再依次写其余字节。

小端法

最低有效字节在最前面的方式成为小端法,这正好和大端法相反,仍然用大端法中举的例子说明:

0x100

0x101

0x102

0x103

78

56

34

12

由上图可见,地址依然从左向右增长,x的最低有效字节在最前面存储,与大端法相反。

字节序标识符

 字节序

<  小端方案

>  大端方案

格式标识符

标识符

描述 字节

x

跳过一个字节 1

b

有符号字节 1

B

无符号字节 1

h

有符号短整数 2

H

无符号短整数 2

i

有符号整数 4

I

无符号整数 4

l

有符号长整数 4

L

无符号长整数 4

Q

无符号long long型整数 8

f

单精度浮点数 4

d

双精度浮点数 8

p

数量和字符 1+数量

s

字符 数量

标识符紧跟字节序标识符的后面,5B代表BBBBB

# _*_ coding: utf-8_*_
import struct
valid_png_header = b'\x89PNG\r\n\x1a\n'
data = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x9a\x00\x00\x00\x8d\x08\x02\x00\x00\x00\xc0'
if data[:8] == valid_png_header:
	width,height = struct.unpack('>LL', data[16:24])
	print('Valid PNG,width', width, 'height', height)
else:
	print('Not a valid PNG')
print('0x9a:', 0x9a)
print('0x8d:', 0x8d)
print(struct.pack('>L', 154))
print(struct.pack('>L', 141))
print(struct.unpack('>2L', data[16:24]))
print(struct.unpack('>16x2L6x', data))
	
	
D:\MyPython>python test2.py
Valid PNG,width 154 height 141
0x9a: 154
0x8d: 141
b'\x00\x00\x00\x9a'
b'\x00\x00\x00\x8d'
(154, 141)
(154, 141)

其他二进制数据工具

其他第三方开源包提供了直观定义和提取二进制数据的方法:

 binio

要先下载安装construct第三方开源包

# _*_ coding: utf-8_*_
from construct import Struct, Magic, UBInt32, Const, String 
fmt = Struct('png', Magic(b'\x89PNG\r\n\x1a\n'),UBInt32('length'),Const(String('type',4),b'IHDR'),UBInt32('width'),UBInt32('height'))
data = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x9a\x00\x00\x00\x8d\x08\x02\x00\x00\x00\xc0'
result = fmt.parse(data)
print(result)
print(result.width, result.height)

结果:
Container:
	length = 13
	type = b'IHDR'
	width = 154
	height = 141
154,141

使binascii()转换字节/字符串

import binascii
valid_png_header = b'\x89PNG\r\n\x1a\n'
print(binascii.hexlify(valid_png_header))	#将八进制打印成十六进制
print(binascii.unhexlify(b'89504e470d0a1a0a'))

D:\MyPython>python test2.py

b'89504e470d0a1a0a'

b'\x89PNG\r\n\x1a\n'

位运算符

整数a(十进制5,二进制0b0101)和整数b(十进制1,二进制0b0001)

比较级整数运算符

python 如何显示u0001 python u32_python