python标准库-内置类型
余弦:我没看过python的书,但我通读过python文档。文档不过一遍,视野会局限。 近日读sqlmap源码,发现自己对于标准库所知甚少,想到knownsec技能表中余弦的一番话,加之最近有意提升English能力,遂意通读python2.7.13官方文档,去粗取精,译成中文,国内虽有一译站点已有翻译,但为参考。然本钱平平,词不达意,技止于此,望看客海涵。
Python标准库-内置类型
主要的内置类型有数字,序列,映射,文件,类,实例和异常。 某些对象类型支持一些操作;特别的,实际上所有对象都可以被比较,测试其真值与否,转换成string(用repr()或略有差异的str()函数,后者在print()函数写出该对象时被隐式调用)。
真值测试
任何对象都可以进行真值测试,使用if或while语句或下面的布尔操作符均可。下列的几种情况被认为是false:
- None
- False
- 数字类型的0,比如0,0L,0.0,0j
- 空的序列,比如’’,(),[]。
- 空的映射,比如{}
- 用户定义类的实例,如果这个类定义了一个
__nonzero__()
或__len__()
方法,且该方法返回的是0或布尔值False。
其他的所有值都被认为是true——因此大部分的对象一般都是true。 操作符和内置函数当需要返回一个布尔值时,往往返回0或者False来代表false,返回1或True来代表true,除非有其他规定(一个重要的差异:布尔操作符or和and总是返回操作数中的一个)。
布尔操作符——and,or,not
以下是bool操作符,按优先级升序排列:
操作符 | 结果 | 注意 |
---|---|---|
x or y | 如果x是false,则返回y,否则返回x | 短路操作符,当x为false时,才会执行y |
x and y | 如果x是false,则返回x,否则返回y | 短路操作符,当x为true时,才会执行y |
not x | 如果x是false,则返回True,否则返回False | not相比较其他非布尔操作符优先级较低,因此not a==b 相当于not(a==b),而a==not b 是语法错误 |
比较
所有对象均支持比较操作符。它们拥有相同的优先级(高于布尔操作符)。比较可以写成链式;比如x < y <= z
和x<y and y<=z
等价(除了y只执行了一次外,且如果x<y是false的话,两个语句都不会执行z,即短路效应)。
操作符 | 意义 |
---|---|
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
== | 等于 |
!= | 不等于 |
is | 对象一致 |
is not | 对象不一致 |
注意:!=也可以写成<>,但这是为了向前兼容。新的代码应该使用!=。
不同类型对象,除了不同的数字类型和字符串类型,永远不要测试相等。这样的对象排序结果永远一致但顺序是随机的(使得异构数组的排序可以生成一致的结果)。此外,某些类型(比如file)只支持退化的比较概念,该类型的两个对象任意之间互不相等。同理,这些对象的排序是一致的但顺序随机。当任意一个操作数是复数时,<、>、=、>=运算符都会抛TypeError。
不同身份的类实例通常不等,除非该类定义了一个__eq__()
方法或__cmp__()
方法。
类实例通常不能与该类的其他实例或其他类型的对象进行排序,除非该类定义了足够的富比较方法(__lt__()
,__le__()
,__gt__()
,__ge__()
)或__cmp__()
方法。
C python实现细节:不同类型对象除了数字型,都是通过类型名字来排序。同类型的对象,如果本身不支持比较,则以地址排序。
两个具有等优先级的操作符,in和not in,仅序列类型支持。
数字类型——int, float, long, complex
有四种数字类型:int,long,float和complex。另外,布尔是int的子类型。python的int在C中用long实现,也就是说至少有32位的精度(sys.maxint
被设为int的最大值,最小值是-sys.maxint-1
)。long类型没有精度限制。float在C中则用double实现。精度信息以及浮点数在机器上的表示方法可以参考sys.float_info
。complex拥有实部和虚部,都是一个float。可以通过z.real
和z.imag
来分别取到(标准库包含额外的数字类型,fractions用于保存分数,decimal用于控制用户定义精度的浮点数)。
数字可以由字面面值逐字创建,也可以由内建函数和操作符创建。未装饰的字面整型(包含二进制,十六进制和八进制数)如果大小没有超出int的表示范围,则会正确的创建出来(yield),如果超出了范围则yield一个long。’‘L或’l’做后缀的整型字面值yield一个long(推荐用‘L’因为’1l’和’11’长得太像了)。拥有小数点或指数符号的字面数值则yield一个float。自面值数型后跟一个’j’或’J’则yield一个虚数,用于得到一个复数。
python完全支持混合运算:当二进制运算操作符用在不同数字类型时,相对“狭义”的类型被转成另一个较“广义”的类型,关系为int < long < float < complex。多个混合数字型比较时采用同样的法则。转换类型时使用int()、long()、float()、complex()。
所有内置数字类型支持下列操作。
操作 | 结果 | 注意条目 |
---|---|---|
x + y | 求x和y的和 | / |
x - y | 求x和y的差 | / |
x * y | x和y的积 | / |
x / y | x除以y | 1 |
x // y | 地板除 | 4,5 |
x % y | x模y | 4 |
-x | x取负 | / |
+x | x不做改变 | / |
abs(x) | x绝对值 | 3 |
int(x) | x转int | 2 |
long(x) | x转long | 2 |
float(x) | x转float | 6 |
complex(re,im) | 实部为re,虚部为im的复数,im默认是0 | / |
c.conjugate() | c的共轭 | / |
divmod(x,y) | (x // y,x % y) | 3,4 |
pow(x,y) | x的y次幂 | 3,7 |
x**y | x的y次幂 | 7 |
注意:
- 对整型除法来说,结果是整数。结果总是朝着小的方向取整:1/2是0,(-1)/2是-1,(-1)/(-2)是0。如果任意一个操作数是long,那么结果也是long,不论值的大小。
- 用int()或long()转float时,会阶段小数点后的值,类似
math.trunc()
。使用math.floor()向下取整,math.ceil()
向上取整。 - 参考内置函数,有完整说明
- 自2.3版本后不再推荐:地板除操作,模操作,divmod()函数都不再对复数可用。取而代之,如果合适的话,可用abs()转成float。
- 同整型除法一致。
- 浮点数也可以接受字符串”nan”和”inf”作为NaN和正负无穷,可以带可选的”+/-“号。
- python定义
pow(0,0)
和0**0
为1,和其他编程语言类似。
所有的numbers.Real
类型(int,long和float)也包含下列操作:
操作 | 结果 |
math.trunc(x) | x截断成整数 |
round(x[, n]) | x对n位向下取整,如果n省略,默认为0 |
math.floor(x) | 满足<=x的最大整数 |
math.ceil(x) | 满足>=x的最小整数 |
整型位操作
位操作仅对整型有效。负数被看做其补足值的两倍大小(假设有个足够大的数,操作中不会溢出)。
二进制位操作符的优先级均比数字操作符低,又都高于比较操作符。唯独~
操作符具有和数字操作符相同的优先级(+和-)。
下表按升序排列位操作符。
操作符 | 结果 | 注意 |
---|---|---|
x 丨 y |
x,y按位或 | — |
x ^ y |
x,y按位异或 | — |
x & y |
下,y按位与 | — |
x << n |
x左移n位 | 1,2 |
x >> n |
x右移n位 | 1,3 |
~x |
x按位取反 | — |
注意:
- n为负数时是非法的,会抛ValueError
- 左移n位等价于乘
pow(2, n)
。如果超出了int的大小,则返回long。 - 右移操作符等价于除以
pow(2, n)
。
整型的额外方法
整型数实现了numbers.Integral抽象基类。此外,它们提供了一个额外的方法:
- int.bit_length()
- long.bit_length()
- 返回用于表达该整型数所需要的位数,不包括符号和开头的0。
>>> n = -37
>>> bin(n)
'-0b100101'
>>> n.bit_length()
6
-
- 更为精确地,如果x非0,那么x.bit_length()是一个独特的整数k(
2**(k-1)<=abs(x)<2**k
)。同样的,如果abs(x)
足够小到有一个可以向下取整的对数运算,那么k=1 + int(log(abs(x), 2))
。如果x是0,则返回0。 - 等价于:
- 更为精确地,如果x非0,那么x.bit_length()是一个独特的整数k(
def bit_length(self):
s = bin(self)
s = s.lstrip('-0b')
return len(s)
浮点数的额外方法
float类型实现了numbers.Real抽象基类。float也具有以下的额外方法。
- float.as_integer_ratio()
- 返回一对整数,这对整数构成的分数和float几近相等。对infinities和NaN抛OverflowError
- float.is_integer()
- 如果float实例是一个有限的整数大小,则返回True,否则返回False。
>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False
有两个方法提供了十六进制字符串和float间的转换。尽管python的float以二进制数存储在内部,十进制串和float间的转换将引起一个向下取整的错误。相对而言,十六进制串允许精确的表示浮点数的规格。当调试时这两个方法很有用。
- float.hex()
- 返回一个表示float数值的十六进制串。对有限的float来说,表达式串永远会以0x开头,以p和指数结尾。
- float.fromhex(s)
- 类方法,返回一个由十六进制串s转成的float。s可以有首尾的空白字符。
float.hex()是一个实例方法,而float.fromhex()是类方法。
十六进制串以这种格式表示:
[sign] ['0x'] integer ['.' fraction] ['p' exponent]
sign是可选的+或-,integer和fraction是十六进制数字符串。exponent是十进制整数,可以有一个可选的符号前缀。integer和fraction中必须至少有一个十六进制数。
注意到指数是十进制写成而非十六进制,最终值为2的exponent次幂乘上系数。比如,十六进制串0x3.a7p10
表示的是(3 + 10./16 + 7./16**2) * 2.0 ** 10
或3740.0。
对3740.0做反向操作则会得到一个不同的十六进制串。
迭代类型
python的容器支持一个迭代的概念。这通过两种不同的方法实现。它们用来允许用户自己定义类来支持迭代。下面描述的序列详细内容,总是支持迭代方法。 对容器对象,为了支持迭代,需要定义个方法:
container.__iter__()
- 返回一个迭代对象。该对象需要支持下面描述的迭代协议。如果一个容器支持不同类型的迭代,那么可以提供额外的方法支持那些迭代器类型的明确的请求。(一个支持多种格式迭代器的对象例子,可以是一个树型结构,该结构支持深度和广度优先搜索。)该方法和在python/C API中对python对象的tp_iter类型结构位置一致。
迭代器对象本身需要支持下面的两个方法,都来自迭代器协议。
iterator.__iter__()
- 返回迭代器对象本身。这被用来允许容器和迭代器使用在for和in语句中。
iterator.next()
- 返回容器的下一个元素。如果没有更多地元素了,抛StopIteration。
python定义了多个迭代器对象去支持生成器和特定的容器类型,字典以及其他的特殊格式。特定的类型除了对迭代器协议的实现以外,并不重要。 协议的目的在于一旦迭代器的next()方法抛StopIteration,它可以继续处理后来的调用。没有遵循这一性质的实现被认为是破损的。
生成器类型
python的生产者提供一个方便的方式来支持迭代协议。如果一个容器对象的__iter__()
方法作为一个生成器实现了,那么他可以自动的返回一个迭代器对象(技术上来说,是一个生成器对象)支持__iter__()
和next()
方法。
序列类型——str,unicode,list,tuple,bytearray,buffer,xrange
共有七个序列类型:字符串,unicode字符串,列表,元组,字节数组,缓冲区,xrange对象。
其他容器可参考内置dict和set类,以及collections模块。
string以单引号或双引号括起来,比如’xyzzy’,”frobozz”。Unicode字符串和字符串很相似,但是在语法上要特别的指定一个前导’u’:u’abc’,u”def”。列表用中括号包裹,元素见用逗号隔开:[a, b, c]。元组成员以逗号分隔,可以有也可以没有小括号包括,但空的元组必须用括号包裹,比如a, b, c
或()
。单一元素的元组必须写成(d,)
。
字节数组以内置的函数bytearray()创建。
缓冲区对象并不由python语法直接支持,但是可以利用内置函数buffer()创建。它们不支持连结和复制操作。
xrange对象和buffers类似,也没有直接语法来创建,但可以用xrange()函数来创建。它们不支持切片,连结和复制操作。对它们使用in
,not in
,min()
,max()
时无效的。
大部分序列类型支持下列操作。in
和not in
操作具有和比较操作同样的优先级。+
和*
操作具有和数字操作符相同的优先级。
下表列出的序列操作优先级以升序排列。s和t是某种序列类型,n,i和j是整型。
操作 | 结果 | 注意条目 |
---|---|---|
x in s | 如果s中某个元素和x等同,返回True,否则返回False | 1 |
x not in s | 如果s中某个元素和x等同,返回False,否则返回True | 1 |
s + t | s和t的连接操作 | 6 |
s * n, n * s | 等同于s自加n次 | 2 |
s[i] | s的第i个元素,以0开始 | 3 |
s[i:j] | 从i到j的切片 | 3,4 |
s[i:j:k] | 从i到j的切片,步长为k | 3,5 |
len(s) | s的长度 | – |
min(s) | s中最小的元素 | – |
max(s) | s中最大的元素 | – |
s.index(x) | s中第一个值为x的元素索引 | – |
s.count(x) | s中值为x的元素个数 | – |
序列类型也支持比较操作。特别的,元组和列表按词典编纂序比较一致的元素。这意味着如果去比较相等,则每个元素都必须都有一个相等的元素,且这两个序列必须是同一个类型,同等长度。
注意:
- 1.当s是string或Unicode string对象时,在
in
和not in
操作中表现的像一个子串测试。 - 2.n小于0时被当做0处理(此时yield一个和s同类型的空序列)。注意s中的元素不是复制的,它们被引用多次。常见于这样的编程写法:
>>> lists = [[]] * 3
>>> lists
[[], [], []]
>>> lists[0].append(3)
>>> lists
[[3], [3], [3]]
[[]]
是一个列表包含一个空列表成员,所以[[]] * 3
产生的3个元素都指向同一个空列表,修改其中的一个,会印象其他所有的。建立不同列表的方法如下:
>>> lists = [[] for i in range(3)]
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
[[3], [5], [7]]
- 3.如果i或j是负数,索引从后向前取。但是注意-0依然是0。
- 4.从i到j的切片是前闭后开区间。如果i或j大于len(s),使用len(s)。如果i被省略,默认为0。如果j被省略,默认为len(s)。如果j小于i,则返回空。
- 5.前闭后开区间,即
0<=n<(j-i)/k
。规则同4。 - 6.如果s和t都是string,python的实现比如CPython通常会进行一个格式
s=s+t
或s+=t
分配的本地优化。可能的话,优化使得二次(O(n^2))时间复杂度的运行时间尽可能的小。优化取决于具体版本和所依赖的实现。对敏感代码的性能来说,更推荐用str.join()
方法,对各种版本和实现来说,该方法确保始终在线性时间复杂度完成。
字符串方法
下面列出了八位字符串和Unicode对象支持的string方法。部分也对bytearray对象适用。
此外,python字符串支持序列类型的方法。输出格式化字符串可以使用模板字符串或%操作符。同样的,可以参考re模块中基于正则表达式的字符串函数。
- str.capitalize()
- 返回一个字符串的拷贝,首字母大写,其余字母小写。
- 对8位字符串来说,该方法依赖于区域设置。
- str.center(width[, fillchar])
- 返回一个width长度的居中字符串str,fillchar用于padding,默认为空白。
- str.count(sub[, start[, end]])
- 返回子串sub在str的start到end切片中出现的次数,子串之间不重叠。
- str.decode([encoding[, errors]])
- 解码用encoding编码的字符串。encoding默认是默认字符串编码。errors用于指定一个错误控制的计划。默认是’strict’,意味着编码错误会抛UnicodeError。其他可能的值分别是’ignore’,’replace’以及通过codecs.register_error()注册的值。
- str.encode([encoding[, errors]])
- 返回一个编码字符串。默认encoding是当前默认字符串编码。errors用于指定错误控制。默认值是’strict’,意味着编码错误会抛UnicodeError。其他可用的值分别是’ignore’,’replace’,’xmlcharrefreplace’,’backslashreplace’以及其他通过codecs.register_error()注册的值。
- str.endswith(suffix[, start[, end]])
- 如果string以suffix结尾则返回True,否则返回False。suffix可以是一个元组,此时string从元组里找。如果有可选的start和end,则以这一切片做比较。
- str.expandtabs([tabsize])
- 返回一个字符串的拷贝,其中所有的tab字符全被替换成一个或多个空格,这取决于当前的列和给定的tab尺寸。tab位置出现在每一个tab尺寸大小的字符处(默认是8,可能是在列0,8,16等等)。扩展字符串,会对当前列置0且逐字符检查。如果字符时tab,就会插入一个到多个字符到结果中直到当前列和下一个tab位置相等。(tab字符本身不拷贝。)如果字符是\n或\r,则拷贝并置当前列为0。其余字符正常拷贝,无论print时展示如何的格式,当前列都会递增。
- str.find(sub[, start[, end]])
- 返回str中找到的子串sub出现的最小索引位,如果有start和end则作为切片。没找到则返回-1。
- str.format(*args, **kwargs)
- 执行字符串格式化操作。调用此方法的字符串可以包含文本自面值或用{}替换的域。每个替换的域代表了其数字序索引的参数,或是一个关键字参数。返回一个字符串的拷贝,每个域被替换成和参数一致。详情可参考格式化字符串语法。
>>> "The sum of 1 + 2 is {0}".format(1+2)
'The sum of 1 + 2 is 3'
- str.index(sub[, start[, end]])
- 和find()类似,但在找不到时会抛ValueError。
- str.isalnum()
- 如果所有字符都是字母或数字,则返回True,哪怕只有一个字符。否则返回False。
- 对8位字符串来说,该方法依赖于区域设置
- 。
- str.isalpha()
- 如果所有字符都是字母,则返回True,哪怕只有一个字符,否则返回False。
- 对8位字符串来说,该方法依赖于区域设置。
- str.isdigit()
- 如果所有字符都是十进制数,则返回True,哪怕只有一个字符,否则返回False。
- 对8位字符串来说,该方法依赖于区域设置。
- str.islower()
- 如果所有区分大小写的字符都是小写的,则返回True,哪怕只有一个字符,否则返回False。
- 对8位字符串来说,该方法依赖于区域设置。
- str.isspace()
- 如果字符串中仅有空白字符,则返回True,哪怕只有一个字符,否则返回False。
- 对8位字符串来说,该方法依赖于区域设置。
- str.istitle()
- 如果是标题字符串则返回True,哪怕只有一个字符,例如大写字母后面必须跟小写字母或无大小写字符。否则返回False。
- 对8位字符串来说,该方法依赖于区域设置。
- str.isupper()
- 如果所有区分大小写的字符都是大写的,则返回True,哪怕只有一个字符,否则返回False。
- 对8位字符串来说,该方法依赖于区域设置。
- str.join(iterable)
- 用str来连接iterable的成员,返回一个字符串。
- str.ljust(width[, fillchar])
- 返回一个左侧合理的长度为width的字符串。用fillchar作padding,默认为空格。如果width小于等于len(s),则返回原始字符串。
- str.lower()
- 返回一个字符串的拷贝,所有字符都被转为小写。
- 对8位字符串来说,该方法依赖于区域设置。
- str.lstrip([chars])
- 返回一个移除前导字符的字符串拷贝。chars是一个字符串,指明被移除的字符集合。如果被省略,或为None,则默认移除所有空白字符。chars并不是一个前缀字符串,而是一个所有值尽可能的组合。
>>> ' spacious '.lstrip()
'spacious '
>>> 'www.example.com'.lstrip('cmowz.')
'example.com'
- str.partition(sep)
- 在第一个sep出现的位置分割字符串,返回一个3元组包含了分割前部分,分割本身和分割后的部分。如果没有找到sep,则返回一个3元组包含字符串本身和两个空字符串。
- str.replace(old,new[,count])
- 返回一个拷贝的字符串,其中所有的子串old被new替换。如果count给定,那么仅仅替换到count个old为止。
- str.rfind(sub[, start[, end]])
- 反向搜索子串sub的位置,start:end为切片。如果找不到,返回-1。
- str.rjust(width[, fillchar])
- 返回一个右侧合理的字符串,长度为width。fillchar用于padding(默认为空格)。如果width小于等于len(s),则返回原始的string。
- str.rpartition(sep)
- 在最后一个搜索到的sep处分割字符串,其他和partition一致。
- str.rsplit([sep[, maxsplit]])
- 返回一个字符串列表,每个元素是string的一个单词,sep作为定界符。如果maxsplit给定了,则最多分maxsplit个词组,从右向左。如果sep没有给定或是None,则空白字符作为定界符。
- str.rstrip([chars])
- 和lstrip类似,这个是从右向左。
- str.split([sep[, maxsplit]])
- 和rsplit类似,这个从左向右。
- str.splitlines([keepends])
- 返回一个字符串列表,按行分割。
- python认为’\r’和’\n’以及”\r\n”为8位字符串的换行符。
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines()
['ab c', '', 'de fg','kl']
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines(True)
['ab c\n', '\n', 'de fg\r', 'kl\r\n']
>>> "".splitlines()
[]
>>> "One line\n".splitlines()
['One line']
>>> ''.split('\n')
['']
>>> 'Two lines\n'.split('\n')
['Two lines', '']
- unicode.splitlines([keepends])
- 返回一个字符串列表,每个成员为unicode的一行,和上面的类似。然而,unicode方法对换行的识别要广泛的多:
Representation | Description |
---|---|
\n | 换行 |
\r | 回车 |
\r\n | 回车换行 |
\v 或 \x0b | 行制表 |
\r 或 \x0c | 表格换行 |
\x1c | 文件分隔符 |
\x1d | 组分割符 |
\x1e | 记录分隔符 |
\x85 | 下一行 |
\u2028 | 行分隔符 |
\u2029 | 段落分隔符 |
- str.startswith(prefix[, start[, end]])
- 如果string以prefix开头,返回True,否则返回False。prefix也可以是一个元组用来遍历。start和end作为可选的切片参数。
- str.strip([chars])
- 返回一个字符串拷贝,去掉头尾的字符。如果chars给定,则去掉该集合中的字符,如果是缺省或为None,那么仅仅移除空白字符。chars不是前缀或后缀,而是一个集合的最大组合。
- str.swapcase()
- 返回一个字符串的拷贝,大小写字母翻转。
- 对8位字符串来说,该方法依赖于区域设置。
- str.title()
- 返回一个首字母大写格式的字符串。
- 该算法利用简单的独立于语法的定义,将连续的一组字母定义为一个单词。很多情况这可以正确的工作,但也意味着对缩略和构成词来说,结果不符合预期。
- 可以用正则表达式来为“’”号构造一个更好的方法:
import re
def titlecase(s):
return re.sub(r"[A-Za-z]+('[A-Za-z]+)?",
lambda mo: mo.group(0)[0].upper() +
mo.group(0)[1:].lower(),
s)
>>> titlecase("they're bill's friends.")
"They're Bill's Firends."
- str.translate(table[, deletechars])
- 返回字符串的一个拷贝,删除所有deletechars中出现的字符。其余字符通过给定的table进行映射转换,转换表必须是长度位256的字符串。
- 可以利用string模块的maketrans()场景一个转换表。对于字符串对象,如果转换只是删除字符,可以设置table为None。
- 对Unicode对象,translate()不接受可选的deletechars参数。相反,它将返回一个字符串的拷贝,其中所有字符通过给定转换表映射,转换表此时必须为Unicode序到Unicode序的转换。未映射的字符原地不动,映射为None的字符被删除。使用codecs模块可以更为灵活的映射字符。
- str.upper()
- 返回字符串的拷贝,所有区分大小写的字符转为大写。
- 对8位字符串来说,此方法依赖于区域设置。
- str.zfill(width)
- 返回数值字符串的左侧0到长度为width的子串。符号前缀会被正确的处理。如果width小于或等于len(s),返回原始字符串。
下列方法只有Unicode对象具有:
- unicode.isnumeric()
- 如果S中只有数值字符串,则返回True,否则返回False。数值字符串包括数字字符和具有数值属性的Unicode,例如U+2155表示分数五分之一。
- unicode.isdecimal()
- 如果S中只有十进制字符,返回True,否则返回False。十进制字符包含数字字符和可构成十进制基数数字的字符。例如U+0660表示阿拉伯数字的0。
格式化字符串操作
string和Unicode对象都有一个特别的内置操作符:%。也被称作格式化字符串操作符。给定format % values(format是string或Unicode对象),%将一个或多个values按照format的格式来一一填充。和C的sprintf()函数很像。若format是Unicode对象,或者任何一个使用%被转换的对象是Unicode对象,结果都会返回一个Unicode对象。
一个转换体语法包含两个或多个字符,且具有下列必须按顺序出现的组成:
- %字符,标志着转换体的开始。
- 映射键(可选的),由圆括号包起来的字符序列组成(例如(somename))。
- 转换标记(可选的),这影响了转换的结果。
- 最低域宽(可选的)。如果指定了星号’*‘,则实际上的宽度由下一个读取的元组中元素来决定,待转换的对象出现在最低域宽后面,且具有一个可选的精度。
- 精度(可选的),通过’.’号跟随精度给出。如果指定了’*‘号,则实际上宽度由元组中下一个元素决定,待转换的数值跟随在精度后面。
- 长度修饰语(可选的)。
- 转换类型。
如果右边的参数时字典(或其他映射类型),则字符串的格式必须包含一个圆括号,映射键到该插入在%字符后的字典。映射键从映射中找到格式化后的值。例如:
>>> print '%(language)s has %(number)03d quote types.' %
... {"language":"Python", "number":2}
Python has 002 quote types.
这种情况下,’*‘号不能出现在format中(因为它们需要一个序列参数列表)。 转换标志如下:
标志 | 意义 |
---|---|
’#’ | 使用下面定义的值替换格式 |
‘0’ | 用0填充整数值 |
’-‘ | 左对齐,如果同时给出了’0’标志,则会覆盖’0’标志 |
’ ‘ | 有符号转换时,正数前应该被留有空白 |
’+’ | 符号字符(‘+/-‘)会在转换时设置在符号数前面(覆盖’ ‘标志) |
可以给出长度修饰符(h,l或L),但是python不需要且会忽略它们。所以比如%ld和%d是一回事。
转换类型如下:
转换 | 意义 | 注意事项 |
---|---|---|
‘d’ | 有符号整型十进制数 | - |
‘i’ | 有符号整型十进制数 | - |
‘o’ | 有符号八进制数 | 1 |
‘u’ | 废弃的类型-和’d’等同 | 7 |
‘x’ | 有符号十六进制数(小写) | 2 |
‘X’ | 有符号十六进制数(大写) | 3 |
‘e’ | 浮点数指数格式(小写) | 3 |
‘E’ | 浮点数指数格式(大写) | 3 |
‘f’ | 十进制浮点数 | 3 |
‘F’ | 十进制浮点数 | 3 |
‘g’ | 浮点数格式。如果指数小于-4或不小于精度则使用小写指数型格式,否则为十进制格式 | 4 |
‘G’ | 浮点数格式。如果指数小于-4或不小于精度则使用大写指数型格式,否则为十进制格式 | 4 |
‘c’ | 单字符(接受整型或单字符字符串) | - |
‘r’ | 字符串(用repr()对python对象进行转换) | 5 |
’s’ | 字符串(用str()对python对象进行转换) | 6 |
’%’ | 参数不被转换,在结果中’%’字符的位置显示原型 | - |
注意:
- 替换格式引起一个前导的’0’进行左填充,如果结果前没有一个’0’则会如此格式化该数值。
- 替换格式引起一个前导的’0x’或’0X’(取决于用’x’或’X’)。
- 替换格式引起结果会包含一个小数点,尽管小数点后没有数值。精度决定了小数点后的数值个数,默认是6个。
- 替换格式引起结果会包含一个小数点,小数点后的0不会被移除。精度决定了小数点后有效数的个数,默认是6个。
- 精度决定了所用的字符的最大个数。
- 如果对象会格式支持unicode字符串,结果字符串也会是一个unicode。精度决定了所用字符的最大个数。
- 参考PEP 237.
因为python字符串含有一个明确的长度,%s转换并不以’\0’作为字符串截断。 更多string操作在string和re模块中定义。
XRange类型
xrange类型是不可变序列,一般用于循环。xrange的优势在于一个xrange对象所用内存量永远是相等的,不管range的大小范围。没有坚持性能的优势。 XRange对象拥有非常少的行为:它们仅仅支持索引,迭代和len()函数。
映射类型-dict
映射对象可以映射可映射(hashable)值到其他任意对象。映射是可变对象。当前仅有一种标准的映射类型,字典。(其他容器请参考内置的list,set和tuple类,以及collections模块。)
字典的键几乎可以是任意值。不可哈希的值,也就是说,值可以包含列表,字典和其他可变的类型(以值来比较而不是object id来比较)不能被用作键。数值类型用于键时,遵守数值比较的规则。如果两个数字比较结果相等(比如1和1.0),那么它们可以用于索引同一个字典条目。(注意,由于计算机存储浮点数是近似值,因此浮点数作为键常常是不明智的。)
创建字典使用逗号作为分隔符,在花括号中分割key: value对。例如,{'jack':4098, 'sjoerd':4127}
或{4098:'jack',4127:'sjoerd'}
,创建字典同样可以用dict构造函数。
- class dict(**kwarg)
- class dict(mapping, **kwarg)
- class dict(iterable, **kwarg)
- 利用可选的参数初始化一个新的字典,关键字参数可能是空的。
- 如果没有给出位置参数,则创建一个空字典。如果位置参数给定,并且是一个映射对象,则创建一个和该映射对象具有相同的键值对的字典。否则,位置参数必须是一个可迭代对象。可迭代对象的每个元素本身还必须是恰好拥有两个元素的对象的迭代器。每个元素的第一个对象作为键,第二个对象作为值。如果键出现超过一次,则后来者覆盖此前的旧值。
- 如果给出了关键字参数,关键字参数和它们的值会被添加到创建的字典中。如果正在添加的键已存在,则依旧覆盖。
- 为了说明,下面的例子都返回一个
{"one":1, "two":2, "three":3}
的字典:
>>> a = dict(one=1, two=2, three=3)
>>> b = {'one':1, 'two':2, 'three':3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True
-
- 实例中的关键字参数仅适用于有效的python标识符所作键。否则,可以用任何有效的键。
- 字典支持一些操作(因此,自定义映射类型也应该支持):
- len(d)
- 返回d的元素个数
- d[key]
- 返回键为key的元素。如果没有则抛KeyError。
- 如果字典的子类定义了一个
__missing__()
方法并且键不存在,则d[key]操作会调用这个方法,以key作为参数。这之后的行为取决于这个call具体的实现。没由其他的方法或操作调用__missing__()
。如果没定义__missing__()
,抛KeyError。__missing__()
必须是一个方法,不能是实例变量:
>>> class Counter(dict):
... def __missing__(self, key):
... return 0
>>> c = Counter()
>>> c['red']
0
>>> c['red'] += 1
>>> c['red']
1
-
- d[key] = value
- 设置d[key]的值为value
- del d[key]
- 移除d中的d[key]项,如果没有则抛KeyError
- key in d
- 如果d有key,则返回True,否则返回False
- key not in d
- 和
not key in d
等价
- 和
- iter(d)
- 返回字典所有键的一个迭代器。这是iterkeys()的简写。
- clear()
- 移除dictionary的所有项
- copy()
- 返回字典的浅拷贝
- fromkeys(seq[, value])
- 创建一个新的字典,用seq和values做键和值。
- fromkeys()是一个类方法,会返回一个新字典。value默认为None。
- get(key[, default])
- 如果key在字典中,返回key的值,否则返回default。如果default没有给定,则default默认为None,因此这个方法永远不会抛KeyError。
- has_key(key)
- 测试key是否在字典中,这个方法不被推荐,更好的是
key in d
。
- 测试key是否在字典中,这个方法不被推荐,更好的是
- items()
- 返回一个字典的(key, value)对拷贝列表。
- CPython实现细节:key和value形成的列表是一个看起来随机的顺序,但实际上并不是随机,这取决于python的具体实现,同时依赖于字典插入和删除的历史。
- 如果items(),keys(),values(),iteritems(),iterkeys()和itervalues()调用过程中没有对字典进行修改,则列表会相当一致。这允许使用zip()创建(value, key)对:
pairs = zip(d.values(), d.keys())
。iterkeys()和itervalues()方法具有同样的关系:pairs = zip(d.itervalues(), d.iterkeys())
。另一种创建同样的列表的方法是pairs = [(v, k) for (k, v) in d.iteritems()]
。
- iteritems()
- 返回一个字典(key,value)对的迭代器。参考dict.items()注释。
- 当增加或删除条目时使用iteritems()会抛RuntimeError,迭代失败时也会抛该异常。
- iterkeys()
- 返回字典键的迭代器,参考dict.items()注释。
- 当增加或删除条目时使用iterkeys()会抛RuntimeError,迭代失败时也会抛该异常。
- itervalues()
- 返回一个字典值的迭代器。参考dict.items()注释。
- 当增加或删除条目时使用itervalues()会抛RuntimeError,迭代失败时也会抛该异常。
- keys()
- 返回字典键的列表。参考dict.items()注释。
- pop(key[, default])
- 如果键在字典中,删除它并返回其值,否则返回default。如果default没有给定且键找不到,则抛KeyError。
- popitem()
- 删除并返回任意的一个(key, value)对。
- popitem()在迭代解构一个字典时非常有用,经常使用在集合算法中。如果字典为空,则抛KeyError。
- setdefault(key[, default])
- 如果key在字典中,返回其值,如果不在,则插入default值,default缺省为None。
- update([other])
- 用other中的key/value对更新字典,覆盖已存在的键值。返回None。
- update()接受另一个字典对象或可迭代的键值对(如元素或其他长度为2的可迭代对象)。如果指定了关键字参数,则字典使用这些值更新:
d.update(red=1, blue=2)
。
- values()
- 返回字典的值的拷贝列表,参考dict.items()注释。
- viewitems()
- 返回字典项(key, value)对的一个新视图(view)。详细请参考view对象。
- viewkeys()
- 返回字典键的新视图。参考view对象。
- viewValues()
- 返回一个字典值的新视图。参考view对象。
- d[key] = value
当且仅当两个字典拥有完全一样的(key,value)对时,才相等。
字典视图对象
dict.viewkeys()
,dict.viewvalues()
和dict.viewitems()
返回的都是视图对象。它们提供一个字典条目的动态视图,也就是说当字典改变时,视图会反射这些变化。
字典视图可以遍历来产生它们各自的数据,且支持成员测试。
- len(dictview)
- 返回字典条目的数量。
- iter(dictview)
- 返回字典键值对或项(表示为(key,value)元组)的迭代器。
- 键值的顺序是任意的,但不是随机的,这取决于python的具体实现,以及字典曾经的增删操作。如果键值和项在遍历过程中不对字典做任何修改,项的顺序将始终如一。这允许用zip()创建(value,key)对:pairs=zip(d.values(),d.keys())。另一种创建相同列表的方式是
pairs = [(v, k) for (k, v) in d.items()]
。 - 迭代视图过程中添加或删除字典中的项可能引发RuntimeError,迭代失败时也抛该异常。
- x in dictview
- 如果x在底层字典中键、值或项(此时x应该是(key, value)元组)中,返回True。
键试图很像集合,因为它们的条目是唯一且可哈希的。如果所有的值都是可哈希的,那么(key,value)对就是唯一且可哈希的,此时项试图也类似集合。(值试图不被看做类似集合,因为条目通常不唯一。)此时这些集合操作是可用的(‘other’指另外一个集合或试图):
- dictview & other
- 返回dictview和其他对象的交集作为新的集合
-
dictview other - 返回二者的并集
- dictview - other
- 返回二者的差集
- dictview ^ other
- 返回只在二者其一中出现的元素,组成一个新集合 一个例子:
>>> dishes = {'eggs':2, 'sausage':1, 'bacon':1, 'spam':500}
>>> keys = dishes.viewkeys()
>>> values = dishes.viesvalues()
>>> # iteration
>>> n = 0
>>> for val in values:
... n += val
>>> print n
504
>>> # keys and values are iterated over in the same order
>>> list(keys)
['eggs', 'bacon', 'sausage', 'spam']
>>> list(values)
[2, 1, 1, 500]
>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['spam', 'bacon']
>>> # set operations
>>> keys & {'eggs', 'bacon', 'salad'}
{'bacon'}
文件对象
文件对象使用C的stdio包实现得,可以用内置的open()函数创建。文件对象也可以从一些其他内置函数和方法返回,比如os.popen()和os.fdopen(),socket对象的makefile()方法。使用tempfile模块可以产生临时文件,一些高级的操作比如拷贝,移动和删除文件目录可以通过shutil模块来实现。
当文件操作由于I/O原因失败时,会抛IOError。它包括出于某种原因该操作未定义的情况,比如seek()一个tty设备或者写一个只读文件等。
文件有如下方法:
- file.close()
- 关闭文件。一个关闭态的文件不能再被读或写。文件在关闭态时,任何依赖这个文件需要打开的操作都会抛ValueError。调用多次close()是被允许的。
- 对python2.5来说,你可以避开显示的调用这个方法如果使用with语句的话。例如,当with代码块结束时,下面的代码会自动关闭f:
from __future__ import with_statement # This isn't required in Python 2.6
with open("hello.txt") as f:
for line in f:
print line,
-
- 对旧版python来说,你可以用下面的语句达到同样效果:
f = open("hello.txt")
try:
for line in f:
print line,
finally:
f.close()
注意:不是所有的类文件类型都支持用with语句来作为上下文管理。如果你用的是类文件对象,那么请用函数contextlib.closing()来直接操作对象。
- file.flush()
- 清空内置buffer,类似stdio的fflush()。对某些类文件对象来说,可能没有这一操作。
flush()不一定写入文件的数据岛磁盘。在flush()后请跟随os.fsync()来确保这种行为。
- 清空内置buffer,类似stdio的fflush()。对某些类文件对象来说,可能没有这一操作。
- file.fileno()
- 返回文件描述符这一整数,用于底层实现IO请求操作。对于较低层次的接口较为有用,如fcntl模块和os.read()及类似函数。
没有真实文件描述符的类文件对象不应该支持该方法!
- 返回文件描述符这一整数,用于底层实现IO请求操作。对于较低层次的接口较为有用,如fcntl模块和os.read()及类似函数。
- file.isatty()
- 如果file连接的是个tty设备,返回True,否则返回False。
没有真实文件描述符的类文件对象不应该支持该方法!
- 如果file连接的是个tty设备,返回True,否则返回False。
- file.next()
- 文件对象是它本身的迭代器,比如iter(f)返回f(除非f被关闭)。当一个file被用作iterator,典型用于for循环中(例如
for line in f: print line.strip()
),next()方法就会被重复的调用。该方法返回下一行输入的内容,当遇到EOF时抛StopIteration(如果文件被写方式打开则未定义该行为)。为了让一个for循环高效遍历每一行(很常见的操作),next()方法使用一个隐藏的预读缓冲区。使用预读缓冲区的结果就是,next()方法和其他文件方法(比如readline())不能一起工作。然而,使用seek()来将文件重定位到一个绝对位置将刷新预读缓冲区。
- 文件对象是它本身的迭代器,比如iter(f)返回f(除非f被关闭)。当一个file被用作iterator,典型用于for循环中(例如
- file.read([size])
- 从文件中读size字节(如果遇到EOF则少于size)。如果size缺省,则一直读到EOF。返回一个字符串型的字节数。如果直接遭遇EOF则返回空串。(对某些文件,像tty,他有道理继续读下去,哪怕遇到EOF)。注意到这个方法可以调用底层C函数fread(),不断尝试获取尽可能的大小的字节。此外,注意出于非阻塞模式时,可能会返回比要求的字节数要少,尽管没有给出size参数。
这是底层函数fread()的封装,在某些极端情形和C函数行为类似,例如对于EOF是否被缓存。
- 从文件中读size字节(如果遇到EOF则少于size)。如果size缺省,则一直读到EOF。返回一个字符串型的字节数。如果直接遭遇EOF则返回空串。(对某些文件,像tty,他有道理继续读下去,哪怕遇到EOF)。注意到这个方法可以调用底层C函数fread(),不断尝试获取尽可能的大小的字节。此外,注意出于非阻塞模式时,可能会返回比要求的字节数要少,尽管没有给出size参数。
- file.readline([size])
- 读file的一行数据。包含结尾的换行符(如果文件该行不完整,则可能没有换行符)。如果size是一个非负数,它作为需要读到的最大字节数并返回不完整的一行。如果size不是0,仅在立即遭遇EOF时返回空串。
- file.readlines([sizehint])
- 一直使用readline()读文件直到遇到EOF,返回一个包含每一行的列表。如果sizehint给定,则由它作为所需读到的最大字节数。类文件的实现对象如果不能实现sizehint,则可能会忽略sizehint,或不能被有效的实现。
- file.xreadlines()
- 返回和iter(f)同样的东西
- file.seek(offset[, whence])
- 设置文件当前位置,例如stdio的fseek()。whence是可选的,默认为os.SEEK_SET或0(绝对文件位置);其他值可以是os.SEEK_CUR或1(相对于当前位置)和os.SEEK_END或2(相对于文件末尾)。该方法没有返回值。
- 例如,f.seek(2,os_SEEK_CUR)的当前位置提升2,f.seek(-3, OS.SEEK_END)将位置设置为倒数第三个字节处。
- 注意是否采用追加方式打开文件(‘a’,’a+’),任何seek()操作将撤销下一个写入操作。如果文件是追加写模式(‘a’),这种方法基本没用。但对’a+’还是有用的。如果在文本模式下,打开该文件,只有tell()返回的偏移是合法的。使用其他偏移都会导致未定义的行为。
- 注意不是所有文件对象都是可以seek的。
- file.tell()
- 返回文件当前位置,和stdio的ftell()很像。
- file.truncate([size])
- 截断文件尺寸。如果可选的size参数给出了,则文件截断到那个尺寸。尺寸默认等于当前位置。当前文件位置不会改变。注意size是否超出了文件的当前尺寸,结果是和平台相关的:可能出现文件没有改变,文件增加了用0填充的指定的尺寸。在Windows、和Unix各种变体中可用。
- file.write(str)
- 向文件写一个字符串。没有返回值。因为要缓冲,所以字符串可能不会在文件中显示,直到flush()和close()方法被调用。
- file.writelines(sequence)
- 向文件写一个字符串序列。sequence可以是任意的产生字符串的可迭代对象,典型的比如字符串列表。该方法没有返回值。(名字和readlines()成双成对,但writelines()却添加换行符。)
文件支持迭代协议。每个迭代元返回readline()返回的同样结果,迭代元在readline()返回空串时终结。
文件对象也提供一些其他有趣的属性。对类文件对象来说他们是不必要的,但是对特别的对象来说他应该被实现以变得有意义。
- file.closed
- 布尔值指示文件对象的当前状态。这是个只读属性;close()方法会改变这个值。对类文件对象来说这是不可用的。
- file.encoding
- 文件所用编码。当Unicode字符串写入文件时,它们会用这个编码转成字节字符串。另外,当文件连到一个终端时,给定的encoding属性很可能被终端所用(如果用户配置了终端,可能该信息不正确)。属性是只读的,对类文件对象来说他不应该存在。他也可以是None,此时表示使用系统默认编码,用于转换Unicode串。、
- file.errors
- Unicode编码错误控制
- file.mode
- 文件的I/O模式。如果文件用open()内置函数创建,则由当时的mode参数决定。这是只读属性,对于类文件对象不应该存在。
- file.name
- 如果用open()创建文件对象,则表示该文件名字。否则,是一个表示该文件对象的字符串,格式为<…>。这是只读属性,类文件对象不应该存在。
- file.newlines
- 如果python用universal newlines激活了(默认)这个只读属性,并且对文件来说,用通用换行读模式打开的话,它会跟踪读取文件时所遇到的换行符的类型。
- file.softspace
- 布尔值,指示print时是否需要一个空白字符打印在另一个值之前。尝试模拟文件对象的类也应该具有科协的softspace属性,该属性值应该被初始化为0。对python中实现的大部分类,这是自动的(注意也许覆盖属性访问的对象会需要)。
注意:改属性不用于控制print语句,而是允许print的实现去跟踪内部状态。
- 布尔值,指示print时是否需要一个空白字符打印在另一个值之前。尝试模拟文件对象的类也应该具有科协的softspace属性,该属性值应该被初始化为0。对python中实现的大部分类,这是自动的(注意也许覆盖属性访问的对象会需要)。
内存试图类型
2.7的新特性。 内存试图对象允许python代码访问一个对象的内部数据,其支持无需复制的缓冲区标准。内存通常以简单的字节解析。
- class memoryview(obj)
- 创建一个引用obj的内存试图。obj必须支持缓冲区标准。内置对象支持该缓冲区协议的包括str和bytearray(unicode不行)。
- memoryview拥有一个元素的概念,由原始对象obj控制的原子内存单元。对很多简单类型来说,比如str和bytearray,元素是一个单一字节,但是对其他第三方类型来说,可能显示更大的元素。
- len(view)返回memoryview中元素的总数。itemsize属性会给出一个单一元素的字节数。
- memoryview支持切片来显示数据。采用一个单一的索引会返回一个str对象形式的单一元素。完整切片以子试图显示:
>>> v = memoryview('abcefg')
>>> v[1]
'b'
>>> v[-1]
'g'
>>> v[1:4]
<memory at 0x77ab28>
>>> v[1:4].tobytes()
'bce'
-
- 如果memoryview所依赖的对象支持改变数据,则memoryview支持切片赋值:
>>> data = bytearray('abcefg')
>>> v = memoryview(data)
>>> v.readonly
False
>>> v[0] = 'z'
>>> data
bytearray(b'z123fg')
>>> v[2] = 'spam'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot modify size of memoryview object
memoryview的尺寸不能够改变。
memoryview有两个方法:
- tobytes()
- 以字节字符串bytesting(类str的一个对象)形式返回缓冲区数据。
>>> m = memoryview("abc")
>>> m.tobytes()
'abc'
- tolist()
- 返回一个整数列表,用于表示缓冲区数据
>>> memoryview("abc").tolist()
[97, 98, 99]
也有一些可用的只读属性:
- format
- 包含视图中每个元素格式(以struct模块的风格)的字符串。默认是’B’,简单的字节字符串。
- itemsize
- 视图中每个元素的字节数
- shape
- 整数元组,ndim属性的长度给定了内存的shape为N维数组。
- ndim
- 表明内存用数组表示时的数组维度,是个整型数。
- strides
- 整数元组,ndim指定了以字节为单位的长度来访问数组每个维度的每个元素。
- readonly
- 布尔值用于表明memory是否是只读的。
上下文管理类型
2.5新特性。
python的with语句支持由上下文管理器定义的运行时上下文概念。这被实现于使用两个独立的方法,允许用户定义的类去定义一个运行时上下文,这个运行时上下文在语句体执行之前出现,在语句体结束后结尾。
上下文管理标准由一对需要被上下文管理对象提供的方法组成,这对方法用于定义一个运行时上下文:
contextmanager.__enter__()
- 输入运行时上下文,返回此对象或另一个相关的运行时上下文对象。此方法返回的值是绑定到使用此上下文管理器with语句的as字句中的标识符。
- 上下文管理的一个例子是返回它自身的文件对象。文件对象从
__enter__()
返回自身,以允许open()在with语句中作为上下文表达式。 - 上下文管理的一个例子是返回一个关联对象,这个关联对象由decimal.localcontext()返回。这些管理器设置活跃的十进制上下文以拷贝原始的十进制上下文并返回拷贝。这允许当前的十进制上下文所用的with语句中做改动,而不影响with语句的外部。
contextmanager.__exit__(exc_type, exc_val, exc_tb)
- 退出运行时上下文并返回一个布尔标记用于表示是否发生了需要被抑制的异常。当在with语句体内发生了异常,参数则包含异常类型,值和traceback信息。否则,三个参数都是None。
- 返回真值会引起with语句抑制该异常并继续运行with后面的语句。否则异常在方法结束执行后继续传播。在该方法执行期间发生的异常会替代在with体内发生的异常。
- 传入的异常不能够再被抛出——取而代之的是,该方法应该返回一个false值来表明方法完成的很顺利,并且不想抑制抛出的异常。这允许上下文管理代码(比如contextlib.nested)轻易的探测
__exit__()
执行的成功与否。
python定义了多个上下文管理器来支持简单的线程同步,快速关闭文件或其他对象,以及对活跃十进制算数上下文的简单操作。特定的类型根据其上下文管理标准的具体实现而不会被特殊的对待。可以参考contextlib模块来找更多例子。
python的生成器和contextlib.contextmanager装饰器提供了一个方便的方法来实现这些协议。如果一个生成器函数是用contextlib.contextmanager装饰器所装饰,它会返回一个实现了必要的__enter__()和__exit__()
方法的上下文管理器,而不是由未修饰的生成器函数产生的迭代器。
其他内置类型
解释器支持几个其他类型对象。其中大部分支持1个或更多操作。
模块
模块的唯一特殊操作是属性访问:m.name,m是模块,name会访问定义在m符号表中的一个名称。模块属性可以被赋值(注意import语句不行,严格来讲,不是模块对象上的一个操作。import foo不会要求名为foo的模块存在,而是需要一个地方对模块来说foo名称在那里有定义)。
每一个模块都有一个特殊的属性:__dict__
。这是个字典,包含了模块的符号表。修改这个字典实际上会修改模块的符号表,但是直接对__dict__
这个属性进行赋值是不可能的(你可以写m.__dict__['a'] = 1
表示m.a为1,但是不能写m.__dict__ = {}
)。修改该属性并不被推荐。
内置于解释器的模块写成这样:<module 'sys' (built-in)>
。如果从一个文件中读取,则被写成<module 'os' from '/usr/local/lib/pythonX.Y/os.pyc'>
。
类和类实例
参考“对象,值和类型”以及“类定义”两节。
函数
函数对象由函数定义创建。对函数对象的唯一操作就是调用它:func(argument-list)
。
有两种类型的函数对象:内置函数对象和用户自定义函数对象。它们都支持相同的操作(调用),但是实现不同,因此其对象类型也不同。
参考“函数定义”一节获取更多信息。
方法
方法是使用属性符号调用的函数。有两种类型:内置方法(list的append())和类实例方法。内置方法在描述类型时会一起描述。
具体实现添加两个特殊的只读属性到类实例方法像这样:m.im_self是方法操作的对象,m.im_func是实现该方法的函数。调用m(arg-1,arg-2,...,arg-n)
完全等价于调用m.im_func(m.im_self,arg-1,arg-2,...,arg-n)
。
类实例方法可以绑定,也可以不绑定,分别表示该方法是通过实例还是类来访问的。当方法未绑定时,其im_self属性是None,如果调用,必须传递一个显示的self对象作为第一个参数。此时,self必须是该未绑定方法类(或其子类)的实例,否则抛TypeError。
类似函数对象,方法对象也支持获取任意属性。然而,由于方法属性实际上存储在底层函数对象(meth.im_func)上,在绑定或未绑定的的方法上设置方法属性都是不允许的。试图设置属性会抛AttributeError。如果想要设置方法属性,则需要在底层函数对象上显式的设置:
>>> class C:
... def method(self):
... pass
>>> c = C()
>>> c.method.whoami = 'my name is method' # can't set on the method
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'instancemethod' object has no attribute 'whoami'
>>> c.method.im_func.whoami = 'my name is method'
>>> c.method.whoami
'my name is method'
更多信息,参考“标准类型层次结构”一节。
代码对象
像函数体那样,用于表示伪编译python代码对象。它们和函数对象不同因为它们并不包含一个全局的执行环境引用。代码对象使用内置的compile()函数创建,可以从它们的func_code属性中提取出函数对象。可以看看code模块。
代码对象可以用exec语句或内置的eval()函数传递执行(而不是一个源码串)。
可以看看标准类型等级获取更多信息。
类型对象
有各种各样的对象类型,一个对象的类型可以通过内置的type()函数获得。在类型上没有特别的操作。标准模块types定义了所有标准内置类型的名字。
类型像这样书写:<type 'int'>
。
Null对象
该对象由那些不会明确返回一个值的函数所返回。它不支持特殊的操作。仅仅只有一个null对象,名为None(内置的名字)。
写成None
。
省略对象
该对象用于切片符号(查看Slicings)。不支持特殊操作。仅仅只有一个省略对象,名为Ellipsis(内置名称)。
写成Ellipsis
。当在一个子脚本中,也可以写成...
,比如seq[...]
。
未实现对象
由比较和二进制操作返回,当它们被要求执行不支持的类型操作时。查看Comparisons了解更多信息。
写成NotImplemented
。
布尔值
布尔值有两个常量对象False和True。用于表示真值。数字上下文中表现为整型0和1。内置函数bool()可以用于转换任何值到布尔型,只要这个值可以被解析为一个真值。
写成False
和True
。
内部对象
查看标准类型等级了解更多信息。它描述了对象栈帧,回溯对象和切片对象。
特殊属性
某些对象类型引起相关性而添加了一些只读属性。一些属性在dir()内置函数中没有报告出来。
object.__dict__
- 字典或其他映射类型用来存储对象(可写的)的属性。
object.__methods__
- 自2.2后不再推荐:使用dir()获取对象属性列表。该属性不再可用。
object.__members__
- 自2.2后不再推荐:使用dir()获取对象属性列表。该属性不再可用。
instance.__class__
- instance实例从属于哪种类
class.__bases__
- 类的基类元组
definition.__name__
- 类,类型,函数,方法,描述符或一般实例的名字。
下列属性仅仅由新式类型对象支持
class.__mro__
- 该属性是一个类元组,当通过方法分辨来查找基类时,被认真对待。
class.mro()
- 此方法可以被元类重写,定义实例自定义方法的解析顺序。它在实例化时调用,结果存在
__mro__
中。
- 此方法可以被元类重写,定义实例自定义方法的解析顺序。它在实例化时调用,结果存在
class.__subclasses__()
- 每个新式类保留对其直接子类的一个弱引用列表。此方法返回这些所有存活引用的列表。示例:
>>> int.__subclasses__()
[<type 'bool'>]