2016-03-23 12 views
1

So sind diese beiden genau Äquivalent vis a vis Leistung (das heißt, ist der generierte Code genau äquivalent):Ist das globale Schlüsselwort inline genau so wie eine lokale Variablendeklaration in Python?

class A(object): 
    const = 'abc' 

    def lengthy_op(self): 
     const = self.const 
     for i in xrange(AVOGADRO): 
      # do something which involves reading const 

und:

const = 'abc' 
class A(object): 

    def lengthy_op(self): 
     global const 
     for i in xrange(AVOGADRO): 
      # do something which involves reading const 
+3

Wenn Sie Variable in Nur-Lese-Weise verwenden Sie Schlüsselwort global nicht brauchen. Ich würde erwarten, dass der Punktzugriff etwas langsamer ist, aber Antworten auf Fragen wie diese sind immer "Messen Sie es". Es ist sowieso nicht sehr wahrscheinlich ein Leistungsengpass. –

+0

@Rogalski: Ich weiß, dass es nicht benötigt wird - meine Frage ist, ob es das globale im lokalen Bereich einreiht (es dem anderen äquivalent macht). Der Punktzugriff wird einmal und die globale Suche auch einmal durchgeführt - meine Frage ist, dass sie danach äquivalent sind - in der Schleife, wo in beiden Fällen nur der Name 'const' verwendet wird. Dies würde sofort von jemandem beantwortet werden, der den Bytecode erzeugen kann, nicht durch Messen, es sollte definitiv sein - außer wenn ich etwas vermisse ... –

+0

Ich würde erwarten, dass der globale Zugriff langsamer ist, da der Variablenname zuerst gesucht wird in der Symboltabelle des lokalen Bereichs, und in der globalen nur, wenn nichts gefunden wird – Ilja

Antwort

1

Nein, sie sind nicht genau gleichwertig , obwohl der Unterschied wahrscheinlich nicht signifikant ist.

class A(object): 
    const = 'abc' 

    def lengthy_op(self): 
     const = self.const 
     for i in xrange(AVOGADRO): 
      # do something which involves reading const 

Dies schafft eine lokale Variable so dass jeder Zugriff von const die LOAD_FAST Opcode verwenden.

const = 'abc' 
class A(object): 

    def lengthy_op(self): 
     # global const 
     for i in xrange(AVOGADRO): 
      # do something which involves reading const 

Dies, mit oder ohne redundante global const verwendet LOAD_GLOBAL den Wert der globalen Variablen für den Zugriff auf const, xrange und AVOGADRO.

In C Python LOAD_GLOBAL wird eine schnelle Wörterbuch-Lookup für den Zugriff auf die Variable (schnell, da die globalen Variablen in einem Wörterbuch mit nur String-Schlüssel und die Hash-Werte sind vorberechnet). Auf der anderen Seite greift LOAD_FAST einfach auf die erste, zweite, dritte usw. lokale Variable zu, was eine Array-Indizierungsoperation ist.

Andere Versionen von Python (z. B. PyPy) können möglicherweise den Zugriff auf die globale Variable optimieren, wobei in diesem Fall möglicherweise kein Unterschied besteht.

Der erste Code (mit n=i+const wie der Körper Loop) auseinanderbauen zu:

>>> dis.dis(A.lengthy_op) 
    5   0 LOAD_FAST    0 (self) 
       3 LOAD_ATTR    0 (const) 
       6 STORE_FAST    1 (const) 

    6   9 SETUP_LOOP    30 (to 42) 
      12 LOAD_GLOBAL    1 (xrange) 
      15 LOAD_GLOBAL    2 (AVOGADRO) 
      18 CALL_FUNCTION   1 
      21 GET_ITER    
     >> 22 FOR_ITER    16 (to 41) 
      25 STORE_FAST    2 (i) 

    8   28 LOAD_FAST    2 (i) 
      31 LOAD_FAST    1 (const) 
      34 BINARY_ADD   
      35 STORE_FAST    3 (n) 
      38 JUMP_ABSOLUTE   22 
     >> 41 POP_BLOCK   
     >> 42 LOAD_CONST    0 (None) 
      45 RETURN_VALUE   

während der zweite Block gibt:

>>> dis.dis(A.lengthy_op) 
    5   0 SETUP_LOOP    30 (to 33) 
       3 LOAD_GLOBAL    0 (xrange) 
       6 LOAD_GLOBAL    1 (AVOGADRO) 
       9 CALL_FUNCTION   1 
      12 GET_ITER    
     >> 13 FOR_ITER    16 (to 32) 
      16 STORE_FAST    1 (i) 

    7   19 LOAD_FAST    1 (i) 
      22 LOAD_GLOBAL    2 (const) 
      25 BINARY_ADD   
      26 STORE_FAST    2 (n) 
      29 JUMP_ABSOLUTE   13 
     >> 32 POP_BLOCK   
     >> 33 LOAD_CONST    0 (None) 
      36 RETURN_VALUE   

Python wird keine lokale Kopie der globalen machen, weil Es gibt keine einfache Möglichkeit, sicherzustellen, dass sich der globale Wert während der Ausführung des Codes nicht ändert. Alles, auch ein anderer Thread oder ein Debugger, könnte den Wert ändern, während die Schleife ausgeführt wird.

+0

A ha - also das Hinzufügen des globalen Schlüsselwortes ist nicht äquivalent zu 'global const; local_const = const; # Verwenden Sie dann local_const. Irgendein Grund warum? Würde es keinen Sinn machen, dass die globale Erklärung dies tut oder etwas kaputtgehen würde? –

+0

Python weiß nicht, dass das globale 'const' nicht variiert, so dass es nicht einfach kopiert werden kann, oder zumindest nicht ohne andere Optimierungen zu machen, die die C-Implementierung von Python nicht macht. – Duncan

+0

Unter dem Strich frage ich mich, ob global nur einen Eintrag zu den lokalen Variablen hinzufügen würde, da es nur gelesen wird - edit: "Alles, auch ein anderer Thread oder ein Debugger, könnte den Wert ändern, während die Schleife ausgeführt wird" - ausgezeichnet Danke, das ist, was ich gesucht habe :) –

0

Ob es schneller oder langsamer ist, hängt tatsächlich von Ihrem Umfang ab, die Bereiche werden in Wörterbüchern gespeichert und je kleiner das Wörterbuch ist, desto schneller (marginal) wird der Zugriff sein. Da Dictionaries als Hash-Sets implementiert sind, ist die Suchleistung O (1).

Jedes Mal, wenn Sie versuchen, eine Variable Python zugreifen werden die Bereiche in dieser Reihenfolge gehen:

  • Local. Der lokale Namespace, der der aktuelle Funktionsumfang ist.
  • Umschließende Funktion Einheimische. Abhängig von der Anzahl der verschachtelten Funktionen/Lambda kann es mehr davon geben.
  • Global. Der globale Bereich, der nur ein anderes Wörterbuch ist (auf das Sie über globals() zugreifen können)
  • Eingebaute. Die Standard-Python-Einbauten, die in allen Bereichen wie list, int usw. verfügbar sind.

Zugriff auf eine Funktion/Klasse Attribut funktioniert in ähnlicher Weise aber beinhaltet:

  • __getattribute__
  • __dict__
  • __getattr__

Und das über alle auch geerbte Klassen.

Der Rest Ihrer Frage beantwortet wurde perfekt von Duncan