返回介绍

命名空间字典

发布于 2024-01-29 22:24:15 字数 2130 浏览 0 评论 0 收藏 0

第19章中,我们学到了模块的命名空间实际上是以字典的形式实现的,并且可以由内置属性__dict__显示这一点。类和实例对象也是如此:属性点号运算其实内部就是字典的索引运算,而属性继承其实就是搜索链接的字典而已。实际上,实例和类对象就是Python中带有链接的字典而已。Python暴露这些字典,还有字典间的链接,以便于在高级角色中使用(例如,编码工具)。

为了了解Python内部属性的工作方式,我们通过交互模式会话加入类,来跟踪命名空间字典的增长方式。在第26章中,我们看到了这种类型的代码的一个简单版本,既然我们已经了解了方法和超类,让我们在这里进一步介绍它。首先,我们定义一个超类和一个带方法的子类,而这些方法会在实例中保存数据。

当我们制作子类的实例时,该实例一开始会是空的命名空间字典,但是有链接会指向它的类,让继承搜索能顺着寻找。实际上,继承树可在特殊的属性中看到,你可以进行查看。实例中有个__class__属性链接到了它的类,而类有个__bases__属性,是一个元组,其中包含了通往更高的超类的链接(我们将在Python 3.0下运行这段代码,名称格式和一些内部属性在Python 2.6中略有不同)。

当类为self属性赋值时,会填入实例对象。也就是说,属性最后会位于实例的属性命名空间字典内,而不是类的。实例对象的命名空间保存了数据,会随实例的不同而不同,而self正是进入其命名空间的钩子。

注意类字典内的其他含有下划线变量名。Python会自动设置这些变量,它们中的大多数都不会在一般程序中使用到,但是有些工具会使用其中的一些变量(例如,__doc__控制第15章讨论过的文档字符串)。

此外,Y是这些语句中创建的第二个实例,即使X的字典已由方法内的赋值语句做了填充,Y最后还是个空的命名空间字典。同样,每个实例都有独立的命名空间字典,一开始是空的,可以记录与同一个类的其他实例命名空间字典中的属性完全不同的属性。

因为属性实际上是Python的字典键,所以其实有两种方式可以读取并对其进行赋值:通过点号运算或者通过键索引运算。

不过,这种等效关系只适用于实际中附加在实例上的属性。因为属性点号运算也会执行继承搜索,所以可以存取命名空间字典索引运算无法读取的属性。例如,继承的属性X.hello无法由X.__dict__['hello']读取。

最后,下面是在第4章和第15章介绍过的内置函数dir用在类和实例对象上的情况。这个函数能用在任何带有属性的对象上:dir(object)类似于object__dict__.keys()调用。不过,dir会排序其列表并引入一些系统属性。在Python 2.2中,dir也会自动收集继承的属性,在Python 3.0中,它包含了从所有类的隐含超类object类继承的名称[1]

亲自动手实验一下这些特殊的属性,来了解命名空间实际上怎么处理它们储存的属性。即使你绝不会在程序内使用这些特殊属性,但是知道它们只是普通的字典,也有助于弄清楚命名空间的一般概念。

[1]正如你所看到的,属性字典内容和dir调用结果会随时间而变。例如,因为Python现在可让内置类型也像类那样可制作子类,dir对内置类型的结果的内容会受到扩展,以包含运算符重载方法,就像这里我们针对Python 3.0下的用户定义类的dir结果一样。一般而言,前后有双下划线的属性名称是解释器专属的属性。类型子类会在第31章再讨论。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文