1. 结语
1.1. '数据模型'一词的由来
数据模型(Data model)来自于官网的第3节, 全文中出现了400次object,个人认为叫"对象模型"似乎更合适,可能叫数据模型的意图是不想被认为python是一门纯粹的面向对象语言吧.
1.2. '魔术方法'
在 Ruby 中也有类似“特殊方法”的概念,但是 Ruby 社区称之为“魔术方法”,而实际上 Python 社区里也有不少人用的是后者。Python 和 Ruby 都利用了这个概念来提供丰富的元对象协议,这既不是魔术也不特殊,而是让语言的用户和核心开发者拥有并使用同样的工具。 考虑一下 JavaScript,情况就正好反过来了.JavaScript 中的对象有不透明的魔术般的特性
,而你无法在自定义的对象中模拟这些行为。比如在 JavaScript 1.8.5 中,用户的自定义对象不能有只读属性,然而不少 JavaScript 的内置对象却可以有。因此在 JavaScript 中,只读属性是“魔术”般的存在,对于普通的 JavaScript 用户而言,它 就像超能力一样。2009 年推出的 ECMAScript 5.1 才让用户可以定义只读属性。 JavaScript 中跟元对象协议有关的部分一直在进化,但由于历史原因,这方面它还是赶不上 Python 和 Ruby。
1.3. python中人人平等
Python 采取了直观的方式来比较对象. ==
运算符比较对象的值,而 is
比较引用. 你可以在自己的类中定义 __eq__
方法,决定 ==
如何比较实例。如果不覆盖 __eq__
方法,那么从 object 继承的方法比较对象的ID,因此这种后备机制认为用户定义的类的各个实例是不同的。
此外,Python 支持重载运算符,== 能正确处理标准库中的所有对象,包括None——这是一个正常的对象.说来python中语言层面来讲所有对象都是正常对象,有相似的行为
1.4. 可变性
如果所有 Python 对象都是不可变的,那么本章就没有存在的必要了。处理不可变的对象时,变量保存的是真正的对象还是共享对象的引用无关紧要。如果a == b
成立,而且两个对象都不会变,那么它们就可能是相同的对象。这就是为什么字符串可以安全 使用驻留。仅当对象可变时,对象标识才重要.
在“纯”函数式编程中,所有数据都是不可变的,如果为集合追加元素,那么其实会创建新的集合。然而,Python不是函数式语言,更别提纯不纯了。在 Python 中,用户定义的类,其实例默认可变(多数面向对象语言都是如此)。自己创建对象时,如果需要不可变的对象,一定要格外小心。此时,对象的每个属性都必须是不可变的,否则会出现类似元组那种行为:元组本身不可变,但是如果里面保存着可变对象,那么元组的值可能会变.
可变对象还是导致多线程编程难以处理的主要原因,因为某个线程改动对象后,如果不正确地同步,那就会损坏数据。但是过度同步又会导致死锁.
1.5. 对象析构和垃圾回收
Python 没有直接销毁对象的机制,这一疏漏其实是一个好的特性:如果随时可以销毁对象,那么指向对象的强引用怎么办? CPython 中的垃圾回收主要依靠引用计数,这容易实现,但是遇到引用循环容易泄露内存,因此 CPython 2.0实现了分代垃圾回收程序,它能把引用循环中不可获取的对象销毁。 但是引用计数仍然作为一种基准存在,一旦引用数量归零,就立即销毁对象。这意味着,在CPython中,这样写是安全的(至少目前如此):
open('test.txt', 'w', encoding='utf-8').write('1, 2, 3')
这行代码是安全的,因为文件对象的引用数量会在 write 方法返回后归零,Python 在销毁内存中表示文件的对象之前,会立即关闭文件。然而,这行代码在 Jython 或 IronPython 中却不安全,因为它们使用的是宿主运行时(Java VM 和 .NET CLR)中的垃圾回收程序,那些回收程序更复杂,但是不依靠引用计数,而且销毁对象和关闭文件的时间可能更长。在任何情况下,包括 CPython,最好显式关闭文件;而关闭文件的最可靠方式是使用 with 语句,它能保证文件一定会被关闭,即使打开文件时抛出了 异常也无妨。使用 with,上述代码片段变成了:
with open('test.txt', 'w', encoding='utf-8') as fp: fp.write('1, 2, 3')
1.6. 参数传递:共享传参
解释 Python 中参数传递的方式时,人们经常这样说:"参数按值传递,但是这里的值是引用."
这么说没错,但是会引起误解,因为在旧式语言中,最常用的参数传递模式有按值传递(如C语言,函数得到参数的副本)和 按引用传递(函数得到参数的指针).在 Python 中,函数得到参数的副本,但是参数始终是引用.因此,如果参数引用的是可变对象, 那么对象可能会被修改,但是对象的标识不变.此外,因为函数得到的是参数引用的副本,所以重新绑定对函数外部没有影响.
还没有评论,来说两句吧...