2017-02-25 1 views
3

Ein Freund fragte kürzlich "Wie behandelt der CPython-Interpreter tatsächlich OOP (Object Orientated Programming)?".Wie behandelt der CPython-Interpreter OOP

Diese Frage endete mich verwirrt, wie ich verstehe, C ist keine objektorientierte Sprache.

Ich versuchte Googling it, Suche StackOverflow und sogar das Lesen der CPython Wiki. Aber ich konnte nichts Nützliches finden.

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()) 

So jetzt will ich wirklich wissen! Wie behandelt der CPython-Interpreter Dinge wie Objekte, wenn er nicht Objekt-orientiert ist?

Antwort

5

Die vollständige Komplexität der OOP-Implementierung von Python geht weit über den Umfang einer Stack Overflow-Antwort hinaus, aber es ist möglich, einen Überblick zu geben. Dies wird viele Details wie Metaklassen, Mehrfachvererbung, Deskriptoren und die C-Level-API beschönigen. Dennoch sollte es Ihnen ein Gefühl dafür geben, warum so etwas möglich ist, sowie einen allgemeinen Eindruck davon, wie es gemacht wird. Wenn Sie die vollständigen Details wünschen, sollten Sie die CPython source code durchsuchen.


Ein Objekt wie eine Instanz Ihrer Person Klasse besteht aus folgenden Dinge:

  • Eine Klasse
  • A dict seine Attribute
  • Andere Sachen halten, die im Moment nicht relevant ist, wie __weakref__.

Eine Klasse ist auch ziemlich einfach. Es hat

  • Basisklasse
  • A dict seine Attribute
  • Andere Sachen halten, die im Moment nicht relevant ist, wie der Klassenname.

Wenn Sie eine Klasse mit einer class Anweisung definieren, bündelt Python einen Zeiger auf die Basisklasse bis sie (oder object wenn Sie nicht ein Pick DID) gepickt und ein dict die Methoden halten Sie definiert sind, und das ist dein neues Klassenobjekt. Es ist ein bisschen wie das folgende Tupel

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

aber kein Tupel. (Bei C-Ebene ist diese Platte fast, aber nicht ganz, als eine Struktur implementiert.)


Wenn Sie eine Instanz der Klasse zu erstellen, bündelt Python einen Zeiger auf die Klasse zusammen und eine neue dict für die Instanzattribute, und das ist Ihre Instanz.Es ist ein bisschen wie das folgende Tupel:

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

aber wieder, kein Tupel. Wiederum ist es fast, aber nicht ganz, als eine Struktur auf C-Ebene implementiert.

Dann läuft es __init__, vorbei __init__ die neue Instanz und was auch immer andere Argumente, die Sie zu Ihrer Klasse zur Verfügung gestellt:

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

Attribut Zuordnung zu setzende Einträgen in dem dict Objekt übersetzt wird, so die Zuordnungen in __init__:

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

Ursache der dict in folgendem Zustand am Ende:

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

Wenn Sie personOne.getInfo() nennen, sucht Python in personOne ‚s dict, dann dict seiner Klasse, dann dict seine Superklasse usw., bis es einen Eintrag für den 'getInfo' Schlüssel findet. Der zugehörige Wert ist die getInfo Methode. Wenn die Methode in einem Klassendikt gefunden wurde, fügt Python personOne als erstes Argument ein. (Die Einzelheiten, wie dieses Argument eingefügt werden kann, sind in der descriptor protocol.)

6

Hier ein kleines Gedankenexperiment: Ihre CPU ist überhaupt nicht "objektorientiert". Stattdessen kann es nur Befehle ausführen wie "Register 1 zu Register 2 hinzufügen und das Ergebnis in Register 3 setzen" und "wenn Register 5 größer als Null ist, dann führe diese goto-Anweisung aus". Und dennoch kann die CPU Python und andere objektorientierte Sprachen irgendwie ausführen. Wie?