Python的面向对象编程实现的完整复杂性远超出了Stack Overflow回答的范围,但是可以提供一个概述。这将忽略很多细节,例如元类、多重继承、描述符和C级API。尽管如此,它应该让你感到为什么实现这样的东西是可能的,并且对如何完成它有一个总体印象。如果您想了解全部细节,您应该浏览
CPython源代码。
一个像你的
Person
类实例的对象包括以下内容:
- 一个类
- 一个持有其属性的字典
- 其他一些目前不相关的东西,比如
__weakref__
。
一个类也很简单。它有:
- 一个基类
- 一个持有其属性的字典
- 其他一些目前不相关的东西,比如类名。
当您使用
class
语句定义一个类时,Python会将指向您选择的基类(如果您没有选择,则为
object
)的指针和保存您定义的方法的字典捆绑在一起,这就是您的新类对象。它有点像以下元组。
Person = (object,
{'__init__': <that __init__ method you wrote>,
'getInfo': <that getInfo method you wrote>},
those irrelevant bits we're glossing over)
但不是元组。在C级别,这个记录几乎是作为结构体实现的,但并非完全相同。
当你创建一个类的实例时,Python会将指向你的类的指针和一个新字典捆绑在一起作为实例的属性,并且这就是你的实例。这有点像下面的元组:
personOne = (Person, {}, those irrelevant bits we're glossing over)
但是,它不是一个元组。在C级别上,它几乎实现为结构体,但并非完全如此。
然后它运行__init__
,将新实例和您提供给类的其他参数传递给__init__
:
Person.__init__(personOne, "Bob", 34)
属性赋值被翻译为在对象的字典中设置条目,因此在
__init__
中的赋值操作如下:
def __init__(self, name, age):
self.name = name
self.age = age
导致字典最终处于以下状态:
{'name': 'Bob', 'age': 34}
当你调用
personOne.getInfo()
时,Python会先查找
personOne
的字典,然后是它所属类的字典,再然后是它的超类的字典等等,直到找到
'getInfo'
键的条目。相关联的值将是
getInfo
方法。如果该方法在类字典中找到,Python将把
personOne
插入为第一个参数。(它如何知道插入该参数的详细信息在
描述符协议中。)