字符编码
字符串其实也是一种数据类型,但是字符串还有一个烦人的问题是编码。
我们知道计算机智能处理数字,如果要计算机处理文本,就必须先把文本转换为数字。最早的计算机采用8个比特为一个字节,一个字节能表示的最大整数就是255(八位二进制最大数11111111=十进制255),想表示更大的数就需要更多的字节。两个字节可以表示的最大数就是二进制下16个1即1111111111111111等于十进制下65535。
最早计算机只使用在英语范围内,所以最早只有127个字符,也就是英文大小写、数字和一些符号,这个编码表就是ASCII编码。这要处理中文明显不够,至少需要两个字节,所以中国制定了自己的GB2312编码。
就这样各国产生了各国的标准,不可避免的会发生冲突,所以早期软件多语言混合的文本会显示乱码。于是发展出了Unicode,它把所有语言统一到一套编码,就解决了乱码的问题。
后来为了解决Unicode编码体型过大,方便传输和存储的目的,发展出了UTF-8,我们现在网页源码上最常见的信息就表明该网页是UTF-8编码,Python编写过程中也要做相应的标注,告诉Python解释器读取源码时按照UTF-8编码读取。
# -*- coding: UTF-8 -*-
在计算机内存中,统一使用的是Unicode编码,当需要保存或者传输时,转换为UTF-8编码。
Python字符串
Python3中,字符串以Unicode编码,也就是说Python支持多语言,例如:
>>> print('你好!Hello!こんにちは!Bonjour!') 你好!Hello!こんにちは!Bonjour!
对于单字符编码,Python提供了一个ord()函数,用来获取字符的整数表示,chr()则把编码转换为对应的字符:
>>> ord('木') 26408 >>> ord('O') 79 >>> ord('人') 20154 >>> chr(75) 'K' >>> chr(24352) '张'
知道了字符的整数编码,我们可以用十六进制来写,这两种方式完全等效。
>>> '\u6728\u4eba\u5f20' '木人张'
encode与decode
Python的字符串str,在内存中以Unicode编码,一个字符会对应若干字节。如果要网络传输或者存储,就要把str变为以字节为单位的bytes。
bytes类型:b左前缀单引号或双引号
x = b'ABC'
bytes在这里每个字符只占一个字节。
encode:unicode编码的str可以用encode()编码为指定编码的bytes
>>> 'Woodmanzhang'.encode('ascii') b'Woodmanzhang' >>> 'Woodmanzhang'.encode('utf-8') b'Woodmanzhang' >>> '木人张'.encode('utf-8') b'\xe6\x9c\xa8\xe4\xba\xba\xe5\xbc\xa0' >>> '木人张'.encode('ascii') Traceback (most recent call last): File "<pyshell#65>", line 1, in <module> '木人张'.encode('ascii') UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
中文超出了ASCII编码范围,就直接报错了。bytes中无法ASCII编码的字节,用\x##显示
decode:从网络或磁盘读取的数据是bytes,使用decode()解码为str
>>> b'Woodmanzhang'.decode('ascii') 'Woodmanzhang' >>> b'\xe6\x9c\xa8\xe4\xba\xba\xe5\xbc\xa0'.decode('utf-8') '木人张'
如果bytes中含有无法解码的字节,decode会报错,可以使用errors=’ignore’忽略错误
>>> b'\xe6\x9c\xa8\xe4\xba\xba\xe5\xbc\xa0'.decode('utf-8') '木人张' >>> b'\xe6\x9c\xa8\xe4\xba\xba\x65\xbc\xa0'.decode('utf-8') Traceback (most recent call last): File "<pyshell#68>", line 1, in <module> b'\xe6\x9c\xa8\xe4\xba\xba\x65\xbc\xa0'.decode('utf-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 7: invalid start byte >>> b'\xe6\x9c\xa8\xe4\xba\xba\x65\xbc\xa0'.decode('utf-8',errors='ignore') '木人e'
len()函数
用来统计字符串str包含多少字符,如果括号内换成bytes,统计计算的就是字节数
>>> len('Woodmanzhang') 12 >>> len('木人张') 3 >>> len(b'Woodmanzhang') 12 >>> len('木人张'.encode('utf-8')) 9 >>> len(b'\xe6\x9c\xa8\xe4\xba\xba\xe5\xbc\xa0') 9
格式化
我们经常收到短信或者提示信息:“亲爱的XX你好,你XX月话费XX元,余额XX元。”这里XXX是变化的变量,所以需要一种格式化字符串的方式在管理这些数据。
Python格式化使用%实现
>>> 'Hello,%s' % '木人张' 'Hello,木人张' >>> '你好,%s,您的账户还有%d元。' %('木人张',1) '你好,木人张,您的账户还有1元。'
%就是用来格式化字符串的,%占位符有几个,后面就有几个变量,或者直接赋值,按顺序对应。如果只有一个占位符,可以去掉括号。
占位符 替换内容
%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数
格式化%指定补零和小数位数的使用:
>>> print('%2d-%02d' % (3, 1)) 3-01 >>> print('%.2f' % 3.1415926) 3.14
%s永远起作用,把任意数据类型转换为字符串
>>> '年龄:%s.会员:%s' % (35,True) '年龄:35.会员:True'
如果是要使用百分号%呢?用%来转义%,也就是%%表示一个%(百分号)
>>> '增长率:%d%%' % 10 '增长率:10%'
format()
格式化字符串的另一种方法,用传入的参数依次替换字符串内的占位符{0}、{1}、….
>>> '你好,{0},您的成绩提升了{1:.1f}%'.format('木人张',10.00) '你好,木人张,您的成绩提升了10.0%'
演示
# -*- coding: UTF-8 -*- # Filename : 演示.py # author by : www.woodmanzhang.com # 让用户输入姓名、成绩,做两年成绩比较 name=input('请输入姓名:') S1 = int(input ('您去年成绩')) S2 = int(input ('您今年成绩')) B = (S2-S1)/S1*100 A = abs(B) if B > 0: print(name,'今年的成绩比去年提高了%.2f%%' % A) elif B < 0: print(name,'今年的成绩比去年降低了%.2f%%' % A) else: print(name,'今年的成绩与去年相同')