说明:本系列文章翻译自 Python 3.5.0 官方文档的 Python 语言参考。翻译不按顺序,学习到哪块就优先翻译哪块,翻译过的文章会在对应标签处添加超链接。考虑到笔者“粗大”的英语水平,翻译的文章如令您不适,请尝试换个方式打开~
翻译有两个目的:一是锻炼自己的英语水平;二是觉得官方文档才是最新,最靠谱的。
欢迎各位多提建议,也欢迎有兴趣的同学共同翻译,共同进步,谢谢。
对象是 Python 对数据的抽象。所有数据在 Python 中以对象或对象之间的关系呈现。(从某种意义上说,也为了与冯·诺依曼的“存储程序计算机”模式一致,代码也使用对象呈现。)
每个对象都有一个身份标识,一个类型和一个值。对象的身份标识一旦被创建就不会改变;你可以认为它是对象在内存中的地址。is
操作符用来比较两个对象;id()
方法返回一个代表对象身份标识的整型。
CPython 实现细节:对 CPython 来说,id(x)
是 x
在内存中的地址。
一个对象的类型决定了该对象支持的操作符(比如:“它是否有长度?”)并且还定义了该类型对象可能的取值。type()
函数返回一个对象的类型(类型本身也是一个对象)。对象的类型就向它的身份标识一样是不可变的。[1]
有些对象的值是可变的。值可变的对象被称为可变对象(mutable);一旦创建,其值就不可改变的对象被称为不变对象(immutable)。(当不变对象容器中包含一个可变对象的引用时,它的值随后者的变化而改变;然而该容器仍被视为不变对象,因为它包含的集合对象是不可变的。所以不变性并不以为着拥有一个不可改变的值,这是个非常微妙的含义。)对象的可变性由它的类型决定;实例、数字、字符串、元组是不变对象,字典和列表是可变对象。
译者注:括号中的内容不好理解,举个例子:
l = ['apple', 'banana'] t = ('beef', l) print(t) # ('beef', ['apple', 'banana']) l.append('grape') print(t)# ('beef', ['apple', 'banana', 'grape'])
t
是不变对象,但它包含有一个l
的引用,l
是个可变对象,当l
的值变化时,t
的值也跟着变化,但由于t
始终持有的都是对l
的引用(不是其他对象的引用),所以t
仍然是一个不变对象。
对象从不会明确销毁;然而,当它们变得不可达时会被垃圾回收(garbage-collected)。一个延迟被垃圾回收或完全被忽略的措施是允许的--垃圾回收如何实现是该措施质量的要素,不应有对象在仍然可用时被回收掉。
CPython 实现细节:CPython当前使用一个引用-计数(reference-counting)方案和(可选的)延迟侦测周期性链接垃圾,一旦对象不可用就尽可能多的回收它们,但此方案并不保证包含循环引用的垃圾被回收。请在gc文档中查看空值循环垃圾回收的信息。其他实现也都不尽相同,并且 CPython也可能会改变。不要相信当对象不可用时会立即立即终止(所以你始终应该明确关闭文件。)
需要注意的是,使用实现的跟踪或调试工具可能会在对象通常可以被回收的情况下保持对象可用。也要注意使用try...catch
语句捕捉异常也可能会保持对象可用。
有些对象--比如打开文件或窗口--会包含对“内部”资源的引用。这些资源在对象被回收后应该被释放,但由于垃圾回收机制不对此作保证,此类对象会提供明确释放内部资源的办法,通常是一个close()
方法。强烈建议程序明确关闭此类对象。try...finally
语句和with
语句为此提供了便捷的方式。
一些对象包含对其他对象的引用,这类对象称作容器。元组、列表、字典都是容器。那些引用是容器值的一部分。多数情况下,我们谈论的容器的值指的是容器中的元素,而不是容器对象的身份标识。然而,当我们谈论容器可变性时,我们指的是直接包含的对象的身份标识。所以,如果一个不变容器(比如元组)包含一个可变对象的引用,它的值随着可变对象的改变而改变。
类型影响对象行为的方方面面。尽管对象身份标识的重要性在一些情况下会被影响:对于不变类型,计算新值的运算实际上返回带有同样类型和值的任意已存在对象的引用,然而对于可变对象着是不被允许的。例如:对于�a = 1; b = 1
, a
和b
可能会(也可能不会)引用同一个值为1的对象,这决定于系统实现;但是对于c = []; d = []
,c
和d
被保证引用两个不同的,唯一的新创建的空列表。(注意,对于c = d = []
,c
和d
只想同一个对象。)
PS:翻译真不是一个轻巧活,自己看的懂容易,翻译出来让大家都看懂却很有难度。如果大家有看不懂的地方请在文章下方留言,如果有翻译不准确的地方也请各位批评指正,谢谢。