Frage

Der __debug__ Variable ist zum Teil praktisch, weil sie sich auf jedes Modul auswirkt.Wenn ich eine andere Variable erstellen möchte, die auf die gleiche Weise funktioniert, wie würde ich das tun?

Die Variable (seien wir originell und nennen sie „foo“) muss nicht wirklich global sein, in dem Sinne, dass wenn ich „foo“ in einem Modul ändere, sie in anderen aktualisiert wird.Es wäre in Ordnung, wenn ich foo festlegen könnte, bevor ich andere Module importiere, und dann würden sie denselben Wert dafür sehen.

War es hilfreich?

Lösung

Ich unterstütze diese Lösung nicht in irgendeiner Weise oder Form. Aber wenn Sie eine Variable zur __builtin__ Modul hinzufügen, wird es zugänglich sein, als ob ein global von einem anderen Modul, das __builtin__ umfasst -., Die alle von ihnen, sind standardmäßig

a.py enthält

print foo

b.py enthält

import __builtin__
__builtin__.foo = 1
import a

Das Ergebnis ist, dass "1" gedruckt wird.

Edit: Das __builtin__ Modul ist als das lokale Symbol __builtins__ zur Verfügung - das ist der Grund für die Diskrepanz zwischen zwei dieser Antworten. Beachten Sie auch, dass __builtin__ umbenannt wurde in python3 builtins.

Andere Tipps

Wenn Sie eine globale modulübergreifende Variable brauchen vielleicht nur einfache globale Variable auf Modulebene genügt.

a.py:

var = 1

b.py:

import a
print a.var
import c
print a.var

c.py:

import a
a.var = 2

Test:

$ python b.py
# -> 1 2

Praxisbeispiel: Djangos global_settings.py obwohl in Django apps Einstellungen verwendet werden durch den Import des Objekt django.conf.settings ).

Definieren Sie ein Modul (nennen wir es „globalbaz“) und haben die Variablen im Inneren definiert. Alle Module mit diesem „pseudoglobal“ sollte die „globalbaz“ Modul importieren, und bezeichnen es mit „globalbaz.var_name“

Dies funktioniert unabhängig von dem Ort der Änderung, können Sie die Variable vor dem Import ändern oder danach. Das importierte Modul wird den neuesten Wert verwenden. (Getestet habe ich diese in einem Spielzeug-Beispiel)

Zur Klarstellung globalbaz.py sieht genauso aus wie folgt aus:

var_name = "my_useful_string"

Ich glaube, dass es viele Umstände, in denen es Sinn macht und es vereinfacht die Programmierung einige Globals zu haben, die sich über mehrere (eng gekoppelt) Module bekannt sind. In diesem Sinne würde Ich mag ein bisschen auf der Idee erarbeiten einen Moduls von Globals, die von diesen Modulen importiert wird, die sie verweisen müssen.

Wenn nur ein solches Modul ist, nenne ich es „g“. Darin ordne ich die Standardwerte für jede Variable I als global behandeln möchten. In jedem Modul, das jeden von ihnen verwendet, verwende ich nicht „von g Import var“, da dies nur zu einer lokalen Variablen, die von g zum Zeitpunkt des Imports nur initialisiert wird. Ich mache die meisten Referenzen in Form g.var und die „g“. dient als ständige Erinnerung, dass ich mit einer Variablen zu tun habe, die möglicherweise zugänglich zu anderen Modulen sind.

Wenn der Wert eines solchen globalen Variablen in einem Modul in irgendeiner Funktion häufig verwendet werden, dann kann diese Funktion eine lokale Kopie machen: var = g.var. Es ist jedoch wichtig zu erkennen, dass Zuweisungen var lokal sind, und globaler g.var kann nicht ohne Referenzierung g.var explizit in einer Zuordnung aktualisiert werden.

Beachten Sie, dass Sie auch mehr solche Globals Module geteilt durch verschiedene Untergruppen Ihres Module Dinge zu halten, kann das ein wenig strenger kontrolliert. Der Grund, warum ich kurze Namen für mein Globals Module ist, den Code zu viel mit Vorkommen von ihnen unübersichtlich zu vermeiden. Mit nur ein wenig Erfahrung, werden sie mnemonic genug mit nur 1 oder 2 Zeichen.

Es ist immer noch möglich, eine Zuordnung zu machen, sagen wir, g.x wenn x in g nicht definiert, und ein anderes Modul kann dann g.x. zugreifen Doch auch wenn der Interpreter es erlaubt, ist dieser Ansatz nicht so transparent, und ich es vermeiden. Es gibt immer noch die Möglichkeit, versehentlich eine neue Variable in g als Ergebnis eines Tippfehlers im Variablennamen für eine Zuordnung zu erstellen. Manchmal ist eine Prüfung von dir (g) ist nützlich, keine Überraschung Namen zu entdecken, die durch einen solchen Unfall entstanden sind.

Sie können die Globals eines Moduls passieren onother:

In Modul A:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

In Modul B:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

Globale Variablen sind in der Regel eine schlechte Idee, aber Sie können dies tun, indem die Zuordnung __builtins__:

__builtins__.foo = 'something'
print foo

Auch die Module selbst sind Variablen, die von jedem Modul zugreifen können. Also, wenn Sie ein Modul namens my_globals.py definieren:

# my_globals.py
foo = 'something'

Dann können Sie, dass von überall verwenden auch:

import my_globals
print my_globals.foo

Mit Modulen statt __builtins__ Modifikation ist im Allgemeinen ein sauberer Weg Globals diese Art zu tun.

Dies ist bereits mit Variablen auf Modulebene möglich.Module sind gleich, unabhängig davon, aus welchem ​​Modul sie importiert werden.Sie können die Variable also zu einer Variablen auf Modulebene in jedem Modul machen, in das sie sinnvoll eingefügt werden soll, und von anderen Modulen darauf zugreifen oder ihr zuweisen.Es wäre besser, eine Funktion aufzurufen, um den Wert der Variablen festzulegen, oder sie zu einer Eigenschaft eines Singleton-Objekts zu machen.Wenn Sie bei einer Variablenänderung Code ausführen müssen, können Sie dies auf diese Weise tun, ohne die externe Schnittstelle Ihres Moduls zu beschädigen.

Normalerweise ist das keine großartige Möglichkeit, Dinge zu erledigen – die Verwendung von Globals ist selten der Fall –, aber ich denke, dass dies die sauberste Art ist, es zu erledigen.

Ich wollte eine Antwort schreiben, dass es ein Fall, in dem der Variable nicht gefunden werden.

Zyklische Importe kann das Modul Verhalten brechen.

Zum Beispiel:

first.py

import second
var = 1

second.py

import first
print(first.var)  # will throw an error because the order of execution happens before var gets declared.

main.py

import first

Auf diese ist beispielsweise sollte es offensichtlich sein, aber in einer großen Code-Basis, kann dies wirklich verwirrend sein.

Das klingt wie die __builtin__ Namensraum zu modifizieren. Um es zu tun:

import __builtin__
__builtin__.foo = 'some-value'

Die __builtins__ nicht direkt verwenden (beachten Sie die zusätzlichen „s“) - offensichtlich kann dies ein Wörterbuch oder ein Modul sein. Vielen Dank für diesen Hinweis auf ΤΖΩΤΖΙΟΥ kann mehr hier .

Jetzt ist foo für den Einsatz überall verfügbar.

ich nicht empfehlen dies in der Regel zu tun, aber die Verwendung dieser ist bis zum Programmierer.

, um sie zuordnen muss, wie oben, nur Einstellung foo = 'some-other-value' es nur gesetzt wird in dem aktuellen Namensraum durchgeführt werden.

Ich benutze diese für ein paar eingebaute in primitiven Funktionen, die ich vermisst fühlte waren wirklich. Ein Beispiel dafür ist eine Suchfunktion, die die gleiche Nutzungs Semantik als Filter hat, eine Karte, reduzieren.

def builtin_find(f, x, d=None):
    for i in x:
        if f(i):
            return i
    return d

import __builtin__
__builtin__.find = builtin_find

Sobald dies ausgeführt wird (zum Beispiel durch den Import in der Nähe Ihres Einstiegspunkt) alle Module können find (), als ob verwenden, natürlich, es wurde gebaut in.

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

. Hinweis: Sie können dies tun, natürlich, mit Filter und einem anderen Leitung für die Länge Null zu testen, oder mit in einer Art seltsamer Linie zu reduzieren, aber ich habe immer das Gefühl es war komisch

Ich konnte erreichen Quer Modul modifizierbar (oder wandelbar ) Variablen durch ein Wörterbuch mit:

# in myapp.__init__
Timeouts = {} # cross-modules global mutable variables for testing purpose
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60

# in myapp.mod1
from myapp import Timeouts

def wait_app_up(project_name, port):
    # wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS']
    # ...

# in myapp.test.test_mod1
from myapp import Timeouts

def test_wait_app_up_fail(self):
    timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS']
    Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3
    with self.assertRaises(hlp.TimeoutException) as cm:
        wait_app_up(PROJECT_NAME, PROJECT_PORT)
    self.assertEqual("Timeout while waiting for App to start", str(cm.exception))
    Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak

Wenn test_wait_app_up_fail startet, ist die tatsächliche maximale Dauer beträgt 3 Sekunden.

fragte ich mich, ob es möglich wäre, einige der Nachteile der Verwendung von globalen Variablen (siehe zB http zu vermeiden: //wiki.c2.com/?GlobalVariablesAreBad ) durch ein Klasse-Namespace statt einem global / Modul-Namensraum mit Werten von Variablen zu übergeben. Der folgende Code zeigt an, daß die beiden Verfahren im wesentlichen identisch sind. Es gibt einen leichten Vorteil bei der Verwendung der Klasse Namespace wie unten erläutert.

Die folgenden Codefragmente zeigen auch die Attribute oder Variablen dynamisch erzeugt werden können, und in beiden global / Modul Namensraum und Klassennamespace gelöscht.

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

Ich nenne das Modul ‚Wand‘, da es verwendet wird Variablen abprallen von. Es wird als ein Raum handeln, um vorübergehend globale Variablen und klassenweite Attribute der leeren Klasse ‚Router‘ zu definieren.

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

Dieses Modul importiert Wand und definiert eine einzelne Funktion sourcefn die eine Nachricht definiert und gibt es von zwei unterschiedlichen Mechanismen, über einen globalen Variablen und einen über die Router-Funktion. Beachten Sie, dass die Variablen wall.msg und wall.router.message definiert sind hier zum ersten Mal in ihrem jeweiligen Namensraum.

dest.py

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

Dieses Modul definiert eine Funktion destfn die die zwei verschiedenen Mechanismen verwendet, um die Nachrichten von der Quelle emittiert wird, zu empfangen. Es gibt die Möglichkeit, dass die Variable ‚msg‘ existiert nicht. destfn löscht auch die Variablen, sobald sie angezeigt wurden.

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

Dieses Modul ruft die zuvor definierten Funktionen in Folge. Nach dem ersten Aufruf der Variablen dest.destfn und wall.msg wall.router.msg nicht mehr existieren.

Die Ausgabe aus dem Programm ist:

global: Hallo Welt!
Router: Hallo Welt!
global: keine Meldung
Router: keine Meldung

Die obigen Codefragmente zeigen, dass das Modul / global und die Klasse / Klassenvariable Mechanismen im Wesentlichen identisch sind.

Wenn viele Variablen geteilt werden, können Namensraum Verschmutzung entweder durch die Verwendung mehrerer wandartigen Module verwaltet werden, z.B. wall1, wall2 usw. oder in einer einzigen Datei mehr Router-Typ-Klassen definieren. Letzteres ist leicht tidier, so stellt vielleicht einen marginalen Vorteil für die Verwendung des klasse variablen Mechanismus.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top