本系列文章译自Python之父 Guido van Rossum 的系列博客“The History of Python”。这个博客系列对我们理解Python及其演变很有帮助,经Guido同意,在这里翻译推荐给大家,希望大家喜欢,也请大家多多指教!
1
对于 Python ,我的一个目标是让所有对象都成为“第一类对象”(first class)。也就是说,所有可以被命名的对象(如数字、字符串、函数、类、模块、方法等等)都有平等的地位,可以赋值给变量、置于列表中、置于字典中、作为参数进行传递等等。
而 Python 的实现方式完全支持这个目标的达成。在 Python 中,所有对象都基于一个 C语言数据结构,不论是变量、列表、函数,还是其它什么对象,不论是简单的整型还是复杂的类对象,都只是使用这个数据结构的不同形式而已。
2
理论上说,让所有对象都成为“第一类对象”是很简单的。不过,关于类,还是有些问题需要解决——怎么让方法成为第一类对象。
比如说,有以下类:
''class A:
'' def __init__(self, x):
'' self.x = x
'' def spam(self, y):
'' print self.x, y
如果方法也是第一类对象,它们就可以被赋值给其它变量,并像其它对象一样使用。比如说,我们可能有语句“s = A.spam”,即把变量 s 指向这个类的方法。然而,方法和一般的函数还是有不一样的地方——方法的第一个参数是这个类的一个实例。
为处理这个问题,我引入了“非绑定方法”。非绑定方法其实只是对实现方法的函数的一个封装,但必须使用该类的实例作为第一个参数。也就是说,如果要像调用函数一样调用 s,就必须传递类 A 的一个实例作为第一个参数,比如说 “a = A(); s(a)”。
(作者注:Python 3 取消了非绑定方法,A.spam 返回的是一个单纯的函数对象。因为在实际使用中,限制第一个参数必须是类的实例其实没什么用,而且在高阶使用中往往成为障碍。有些人将其称作“傻傻的self”(duck typing self),感觉也说得没错)
一个相关的问题是,用户有可能在代码中直接通过类的实例来引用类的方法,比如说,“a = A(); s = a.spam”。为应对这种情况,我又引入了“绑定方法”——也是对实现方法的函数的一个封装,但在封装中隐式存储了这个实例,之后调用“s()”的时候,默认把这个实例作为第一个参数。
具体实现上,“绑定方法”和“非绑定方法”用的是同一个内部对象,这个对象的一个属性即指向实例的指针。如果这个指针是 None,就是非绑定方法,否则就是绑定方法。
3
绑定方法与非绑定方法看上去只是一个无关紧要的细节,但其实是类的重要运作机制。
当代码中出现“a.spam()”这样的语句时,底层实际上会执行两个步骤:首先,查找 “a.spam”并返回绑定方法——一个可调用的函数对象;接着,执行操作符“()”,调用并将参数传递给这个函数对象。
公众号:ReadingPython
博客地址:Python的历史【译】
网友评论