2012-11-15 11 views
6

Ich muss einen Import in __init__() Methode haben (weil ich diesen Import nur ausführen muss, wenn ich die Klasse instanziiere).Python-Import in __init __()

Aber ich kann nicht sehen, dass der Import außerhalb __init__(), ist der Umfang auf __init__ begrenzt? wie macht man?

+6

Der Import ist an den Umfang gebunden, in den er importiert wurde ... Ich habe das Gefühl, dass Sie das nicht tun wollen, was ist Ihr Anwendungsfall? –

+0

Warum möchten Sie es nur in '__init __()' importieren, wenn Sie es auch in anderen Bereichen benötigen? –

+1

weil ich eine Klasse mit einer Abhängigkeit habe, und ich möchte, dass diese Abhängigkeit nur geladen wird, wenn jemand diese Klasse verwendet (erstellt eine Instanz) – tapioco123

Antwort

8

Importierte Namen sind an den aktuellen Bereich gebunden, sodass ein Import innerhalb einer Funktion nur an einen lokalen Namen gebunden wird.

Wenn Sie unbedingt haben etwas __init__ zu importieren, die dann global verfügbaren sein muss, markieren Sie den importierten Namen als global zuerst:

>>> def foo(): 
...  global sys 
...  import sys 
... 
>>> sys 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'sys' is not defined 
>>> foo() 
>>> sys 
<module 'sys' (built-in)> 

aber dies führt in der Regel zu seltsam und wunderbar schwer Fehler zu lokalisieren . Tun Sie das nicht, machen Sie stattdessen Ihre Importe im Modulbereich.

Wenn Sie den importierten Namen innerhalb anderer Klassen-Methoden benötigen, können Sie auch den importierten Namen einer Instanz Variablen zuweisen:

class Foo(object): 
    def __init__(self): 
     import os 
     self.join = os.path.join 

aber wieder, das ist nicht die beste Praxis zu verwenden.

+0

Was würden Sie dann empfehlen? Ich habe eine abstrakte Klasse (abc) und eine Klasse, die Klassen enthält, die diese abc-Klasse implementieren. Und eine Funktion, die auf einer Zeichenkette basiert, sucht nach einer Klasse, die diese abc-Klasse implementiert und dann ihre Funktion prepare (benötigt von abstract) aufruft. Diese Funktionen erfordern möglicherweise völlig andere Dinge, wie zum Beispiel sqlite und andere xml-Parser. –

+0

Vielleicht diese Implementierungen in ihr eigenes Modul? Aber wirklich, was ist das Problem, wenn man nur diese Importe auf die oberste Ebene bringt? –

+0

Eigenes Modul kommt nicht in Frage, da dir() zu verschleiert ist und zu viele Dinge zu validieren (und möglicherweise Code zu brechen). Auf oberster Ebene kommt das auch nicht in Frage, da einige der Klassen große Module wie sqlite, tkinter, minidom usw. benötigen und wir diese nicht beim Modulimport importieren wollen, sondern nur eine Teilmenge davon nach welcher Klasse wir benötigen. –

4

Sie können es einfach wieder an anderen Orten importieren, die Sie benötigen - es wird nach dem ersten Mal im Cache gespeichert, so dass dies relativ preiswert ist.

Alternativ könnten Sie die aktuellen globalen Namespaces mit etwas wie globals()['name'] = local_imported_module_name ändern.

EDIT: Für die Aufzeichnung wird sicherlich die globals() Funktion obwohl mit arbeiten, ich denke, eine „sauberere“ Lösung des Modulnamen global und dann import es, wie einige andere Antworten erwähnt haben zu erklären wäre.

+2

'importieren Sie es wieder' ist die richtige Lösung. Es ist kostenlos, da Modulimporte global in 'sys.modules' zwischengespeichert werden. – katrielalex

+1

@katrielalex: Das meinte ich mit dem Teil "es wird zwischengespeichert". – martineau

+0

Zustimmen - Ich habe nur betont =) – katrielalex

2

Wenn Sie das Ergebnis Ihrer importieren mögen auf andere Objekte der Klasse sichtbar sein, müssen Sie das resultierende Objekt aus dem Import eine Klasse oder Instanz-Variable

Zum Beispiel zuzuordnen:

>>> class Foo(object): 
... def __init__(self): 
...  import math 
...  self.bar = math.pi 
... def zoo(self): 
...  return self.bar 
... 
>>> a = Foo() 
>>> a.zoo() 
3.141592653589793 
+0

Das ist eine gute Idee, aber ich denke, das OP möchte etwas mehr wie 'Foo.math =' oder 'self.math = math' - also das ganze Modul. – martineau

3

Die Anweisung import macht die importierten Namen nur für den aktuellen Bereich verfügbar. Ein import foo innerhalb Ihrer __init__ erstellt eine foo, die nur innerhalb der __init__-Methode sichtbar ist.

Sie können entweder import foo zu einer beliebigen Methode hinzufügen, die auf das Modul zugreifen muss, oder wenn Sie den Import über einen erneuten schreiben, verwenden Sie das Schlüsselwort global, um es in den Modulbereich zu importieren.

Verwandte Themen