Learn Python (day 3) :字符串

来源:互联网 发布:杭州旅游 知乎 编辑:程序博客网 时间:2024/04/28 15:17

在Python 3,所有的字符串都是使用Unicode编码的字符序列。

导致的问题是:在vs2013里面写Python代码时候,如果使用'''作为注释,vs2013会把它编码成UTF-8 ascii。导致运行出错。(本人还未找到解决方案,如果有人有办法解决请留言!!!)

解决方法:

Python 3会假定我们的源码 — 即.py文件 — 使用的是utf-8编码方式。

☞Python 2里,.py文件默认的编码方式为ascii。Python 3的源码的默认编码方式为utf-8

如果想使用一种不同的编码方式来保存Python代码,我们可以在每个文件的第一行放置编码声明(encoding declaration)。以下声明定义.py文件使用windows-1252编码方式:
# -*- coding: windows-1252 -*-


从技术上说,字符编码的重载声明也可以放在第二行,如果第一行被类unix系统中的hash-bang命令占用了。
#!/usr/bin/python3
# -*- coding: windows-1252 -*-


这段话没看懂!

>>> import humansize>>> import sys>>> '1MB = 1000{0.modules[humansize].SUFFIXES[1000][0]}'.format(sys)'1MB = 1000KB'
sys模块保存了当前正在运行的Python实例的信息。由于已经导入了这个模块,因此可以将其作为format()方法的参数。所以替换域{0}指代sys模块。
sys.modules is a dictionary of all the modules that have been imported in this Python instance. The keys are the module names as strings; the values are the module objects themselves. So the replacement field {0.modules} refers to the dictionary of imported modules. sys.modules是一个保存当前Python实例中所有已经导入模块的字典。模块的名字作为字典的键;模块自身则是键所对应的值。所以{0.modules}指代保存当前己被导入模块的字典。
sys.modules['humansize']即刚才导入的humansize模块。所以替换域{0.modules[humansize]}指代humansize模块。请注意以上两句在语法上轻微的不同。在实际的Python代码中,字典sys.modules的键是字符串类型的;为了引用它们,我们需要在模块名周围放上引号(比如 'humansize')。但是在使用替换域的时候,我们在省略了字典的键名周围的引号(比如 humansize)。在此,我们引用PEP 3101:字符串格式化高级用法,“解析键名的规则非常简单。如果名字以数字开头,则它被当作数字使用,其他情况则被认为是字符串。”
sys.modules['humansize'].SUFFIXES是在humansize模块的开头定义的一个字典对象。 {0.modules[humansize].SUFFIXES}即指向该字典。
sys.modules['humansize'].SUFFIXES[1000]是一个si(国际单位制)后缀列表:['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']。所以替换域{0.modules[humansize].SUFFIXES[1000]}指向该列表。
sys.modules['humansize'].SUFFIXES[1000][0]即si后缀列表的第一个元素:'KB'。因此,整个替换域{0.modules[humansize].SUFFIXES[1000][0]}最后都被两个字符KB替换。



Python的bug(不知道算不算。版本Python 3.4.2)

>>> '{0:.1f} {1}'.format(698.24, 'GB')'698.2 GB'>>> '{0:.1f} {1}'.format(698.25, 'GB')'698.2 GB'>>> '{0:.1f} {1}'.format(698.29, 'GB')'698.3 GB'>>> '{0:.1f} {1}'.format(698.26, 'GB')'698.3 GB'>>> '{0:.1f} {1}'.format(698.251, 'GB')'698.3 GB'>>> 698.25698.25>>> '{0:.1f} {1}'.format(698.25, 'GB')'698.2 GB'>>> '{0:.1f} {1}'.format(698.2501, 'GB')'698.3 GB'>>> '{0:.1f} {1}'.format(698.250, 'GB')'698.2 GB'


String vs. Bytes

字节即字节;字符是一种抽象。一个不可变(immutable)的Unicode编码的字符序列叫做string。一串由0到255之间的数字组成的序列叫做bytes对象。

>>> by = b'abcd\x65'  ①>>> byb'abcde'>>> type(by)          ②<class 'bytes'>>>> len(by)           ③5>>> by += b'\xff'     ④>>> byb'abcde\xff'>>> len(by)           ⑤6>>> by[0]             ⑥97>>> by[0] = 102       ⑦Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: 'bytes' object does not support item assignment
使用“byte字面值”语法b''来定义bytes对象。byte字面值里的每个字节可以是ascii字符或者是从\x00到\xff编码了的16进制数。
bytes对象的类型是bytes。
跟列表和字符串一样,我们可以通过内置函数len()来获得bytes对象的长度。
使用+操作符可以连接bytes对象。操作的结果是一个新的bytes对象。
连接5个字节的和1个字节的bytes对象会返回一个6字节的bytes对象。
一如列表和字符串,可以使用下标记号来获取bytes对象中的单个字节。对字符串做这种操作获得的元素仍为字符串,而对bytes对象做这种操作的返回值则为整数。确切地说,是0–255之间的整数。
bytes对象是不可变的;我们不可以给单个字节赋上新值。如果需要改变某个字节,可以组合使用字符串的切片和连接操作(效果跟字符串是一样的),或者我们也可以将bytes对象转换为bytearray对象。


>>> by = b'abcd\x65'>>> barr = bytearray(by)  ①>>> barrbytearray(b'abcde')>>> len(barr)             ②5>>> barr[0] = 102         ③>>> barrbytearray(b'fbcde')
使用内置函数bytearray()来完成从bytes对象到可变的bytearray对象的转换。
所有对bytes对象的操作也可以用在bytearray对象上。
有一点不同的就是,我们可以使用下标标记给bytearray对象的某个字节赋值。并且,这个值必须是0–255之间的一个整数。


我们决不应该这样混用bytes和strings。

>>> by = b'd'>>> s = 'abcde'>>> by + s                       ①Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: can't concat bytes to str>>> s.count(by)                  ②Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: Can't convert 'bytes' object to str implicitly>>> s.count(by.decode('ascii'))  ③1
不能连接bytes对象和字符串。他们两种不同的数据类型。
也不允许针对字符串中bytes对象的出现次数进行计数,因为串里面根本没有bytes。字符串是一系列的字符序列。也许你是想要先把这些字节序列通过某种编码方式进行解码获得字符串,然后对该字符串进行计数?可以,但是需要显式地指明它。Python 3不会隐含地将bytes转换成字符串,或者进行相反的操作。
好巧啊…这一行代码刚好给我们演示了使用特定编码方式将bytes对象转换成字符串后该串的出现次数。
所以,这就是字符串与字节数组之间的联系了:bytes对象有一个decode()方法,它使用某种字符编码作为参数,然后依照这种编码方式将bytes对象转换为字符串,对应地,字符串有一个encode()方法,它也使用某种字符编码作为参数,然后依照它将串转换为bytes对象。在上一个例子中,解码的过程相对直观一些 — 使用ascii编码将一个字节序列转换为字符串。同样的过程对其他的编码方式依然有效 — 传统的(非Unicode)编码方式也可以,只要它们能够编码串中的所有字符。


>>> a_string = '深入 Python'         ①>>> len(a_string)9>>> by = a_string.encode('utf-8')    ②>>> byb'\xe6\xb7\xb1\xe5\x85\xa5 Python'>>> len(by)13>>> by = a_string.encode('gb18030')  ③>>> byb'\xc9\xee\xc8\xeb Python'>>> len(by)11>>> by = a_string.encode('big5')     ④>>> byb'\xb2`\xa4J Python'>>> len(by)11>>> roundtrip = by.decode('big5')    ⑤>>> roundtrip'深入 Python'>>> a_string == roundtripTrue
a_string是一个字符串。它有9个字符。
by是一个bytes对象。它有13个字节。它是通过a_string使用utf-8编码而得到的一串字节序列。
by还是一个bytes对象。它有11个字节。它是通过a_string使用GB18030编码而得到的一串字节序列。
此时的by仍旧是一个bytes对象,由11个字节组成。它又是一种完全不同的字节序列,我们通过对a_string使用Big5编码得到。
roundtrip是一个字符串,共有9个字符。它是通过对by使用Big5解码算法得到的一个字符序列。并且,从执行结果可以看出,roundtrip与a_string是完全一样的。 





















0 0
原创粉丝点击