2016-08-02 5 views
3

Beide Codes scheinen ähnliche Leistung zu haben. Wie funktioniert der Bereich in diesem Fall? Ist einer von ihnen besser als der andere? Gibt es einen besseren Weg, um das gleiche Verhalten zu erreichen?Python-Thread-Bereich

Code 1:

class ex: 
    b = 6 
    def foo(self, a): 
    def fooHandler(a): 
     while True: 
     print a 
     time.sleep(1) 
    threading.Thread(target=fooHandler, args=(a,)).start() 
x = ex() 
x.foo(10) 
x.foo(100) 
x.foo(1000) 

Code 2:

class ex: 
    b = 6 
    def foo(self, a): 
    def fooHandler(): 
     while True: 
     print a 
     time.sleep(1) 
    threading.Thread(target=fooHandler).start() 
x = ex() 
x.foo(10) 
x.foo(100) 
x.foo(1000) 
+0

die Einrückung wurde durcheinandergebracht, als ich von meinem Editor kopierte, sollte es jetzt funktionieren – user3019917

+0

Sie möchten dies lesen: http://stackoverflow.com/questions/4020419/why-arent-python-nested-functions- called-closures – dmitri

+0

@dmitri der Link war hilfreich :) danke – user3019917

Antwort

1

Nun, es ist ein Unterschied in dem generierten Code (zumindest bei der Verwendung von CPython 2.7.12):

def runThread(a): 
    def threadFunc(): 
     while True: 
      print a 
      time.sleep(1) 

    t = threading.Thread(target=threadFunc) 
    t.start() 

einen LOAD_GLOBAL Opcode für a innerhalb threadFunc() ausstellt (Ausgang von inspect.dis.dis()):

8   9 LOAD_GLOBAL    1 (a) 

während

def runThread(a): 
    def threadFunc(a): 
     while True: 
      time.sleep(1) 

    t = threading.Thread(target=threadFunc, args=(a,)) 
    t.start() 

wird Thema eines LOAD_FAST Opcode:

8   9 LOAD_FAST    0 (a) 

Die LOAD_FAST geschieht, weil der Compiler weiß, dass a Parameter ist und somit die Suche benötigt nur WRT passieren. in den aktuellen Namespace. LOAD_FAST (daher der Name) ist möglicherweise schneller als LOAD_GLOBAL, aber wenn Sie über die Unterschiede in Bezug auf die Leistung denken müssen, sollten Sie Python überhaupt nicht verwenden.

Und ja, alles schreit auch "Implementierungsdetails" zu mir.

Scope-Import a von einem äußeren Bereich gibt Ihnen zusätzliche Flexibilität, da Sie noch a noch ändern können, nachdem der Thread bereits ausgeführt wird. Bei der Übergabe von a als Parameter an die Thread-Funktion ist diese Möglichkeit mehr oder weniger weg. In jedem Fall würde ich die erste als Antipattern betrachten, es sei denn, a ist die Thread-Beendigung-Flag.

0

Das hat nichts mit Threading zu tun, es ist nur eine Frage der Wert von verschachtelten Bereich mit explizit als vs. vorbei Argument und Verwendung von lokalen Bereich.

Es spielt keine Rolle, welchen Ansatz Sie in diesem Fall verwenden. Sie verwenden in beiden Fällen den gleichen Wert. Das Nachschlagen im verschachtelten Bereich ist teurer, aber nur trivial (es entspricht im Wesentlichen einem einzelnen dict-Lookup, bei dem lokale Lookups näher an der Array-Zugriffsleistung liegen).

Wenn Sie während der Funktion die Bindung von a ändern mussten, konnten Sie dies nicht mit implizitem geschachteltem Bereichszugriff tun (Sie müssten einen anderen Namen verwenden), weil Sie nicht lesen und schreiben können Bereichsvariable in Python 2 (ohne das Schlüsselwort nonlocal). Die Verwendung eines anderen Namens (ursprünglich auf a gesetzt) ​​wäre in jedem Fall ähnlich wie die Annahme als Argument, also auch hier kein wesentlicher Unterschied.