CPython Interpreter如何处理OOP

时间:2017-02-25 03:00:14

标签: python c oop cpython

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

这个问题让我很困惑,因为我知道C不是面向对象的语言。

我尝试Googling it,搜索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() )

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

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:5)

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

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将指向你的类的指针和一个新的dict捆绑在一起,用于实例的属性,这就是你的实例。它有点像下面的元组:

personOne = (Person, {}, those irrelevant bits we're glossing over)

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

然后它运行__init__,传递__init__新实例以及您向班级提供的其他任何参数:

Person.__init__(personOne, "Bob", 34)

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

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

导致dict以下列状态结束:

{'name': 'Bob', 'age': 34}

当你致电personOne.getInfo()时,Python查看personOne的字典,然后查看其类别的字典,然后查看其超类的字典等,直到它找到'getInfo'键的条目。关联的值将是getInfo方法。如果在类dict中找到该方法,Python将插入personOne作为第一个参数。 (它如何知道插入该参数的详细信息在descriptor protocol。)