CPython Interpreter如何处理OOP

Jon*_*ris 3 c python oop cpython

一位朋友最近问过"CPython Interpreter如何实际处理OOP(面向对象编程)?".

这个问题最终让我困惑,因为我理解C不是面向对象的语言.

我尝试使用Google搜索,搜索StackOverflow甚至阅读CPython Wiki.但我找不到任何有用的东西.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def getInfo(self):
        return "Name: " + self.name + "\nAge: " + str(self.age)

# How the heck does CPython handle this?
personOne = Person("Bob", 34)
personTwo = Person("Rob", 26)

print( personOne.getInfo() )
print( personTwo.getInfo() )
Run Code Online (Sandbox Code Playgroud)

所以现在我真的想知道!CPython Interpreter如何处理像Objects这样的东西,如果它本身不是面向对象的?

nib*_*bot 5

这是一个小小的思考实验:你的CPU根本不是"面向对象的".相反,它只能执行诸如"将寄存器1添加到寄存器2并将结果放入寄存器3"和"如果寄存器5大于零,则执行此goto语句"之类的指令.但不知何故,CPU可以运行Python和其他面向对象的语言.怎么样?


use*_*ica 5

Python的OOP实现的完全复杂性远远超出了Stack Overflow答案的范围,但是可以提供概述.这将掩盖许多细节,如元类,多重继承,描述符和C级API.不过,它应该让你了解为什么实现这样的事情是可能的,以及对它是如何完成的总体印象.如果您想要完整的详细信息,您应该浏览CPython源代码.


类的实例之Person类的对象包含以下内容:

  • 一类
  • 一个持有其属性的字典
  • 其他与现在无关的东西,比如__weakref__.

课程也很简单.它有

  • 基类
  • 一个持有其属性的字典
  • 其他与现在不相关的东西,比如班级名称.

当你用一个class语句定义一个类时,Python会捆绑一个指向你选择的基类的指针(或者object如果你没有选择一个)和一个包含你定义的方法的dict,那就是你的新类对象.它有点像下面的元组

Person = (object,
          {'__init__': <that __init__ method you wrote>,
           'getInfo': <that getInfo method you wrote>},
          those irrelevant bits we're glossing over)
Run Code Online (Sandbox Code Playgroud)

但不是一个元组.(在C级别,此记录几乎(但不完全)实现为结构.)


当您创建类的实例时,Python会将指向您的类的指针和实例属性的新dict捆绑在一起,这就是您的实例.它有点像以下元组:

personOne = (Person, {}, those irrelevant bits we're glossing over)
Run Code Online (Sandbox Code Playgroud)

但同样,不是一个元组.同样,它几乎(但不完全)在C级实现为结构.

然后它运行__init__,传递__init__新实例和您提供给您的类的任何其他参数:

Person.__init__(personOne, "Bob", 34)
Run Code Online (Sandbox Code Playgroud)

属性赋值转换为对象dict中的设置条目,因此分配在__init__:

def __init__(self, name, age):
    self.name = name
    self.age = age
Run Code Online (Sandbox Code Playgroud)

导致dict最终处于以下状态:

{'name': 'Bob', 'age': 34}
Run Code Online (Sandbox Code Playgroud)

当你调用时personOne.getInfo(),Python查看personOne的是dict,然后是它的类的dict,然后是它的超类的dict等,直到找到'getInfo'键的一个条目.关联的值将是getInfo方法.如果在类dict中找到该方法,则Python将personOne作为第一个参数插入.(它如何知道插入该参数的细节在描述符协议中.)