global?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Hey.
Ich hab mal eine Frage ... Wozu gibt es denn global, wenn man es nicht benutzen soll?
Ich weiß warum global (in den Fällen die ich kenne) nicht sinnvoll ist.
Aber dann muss es ja irgendwelche Anwendungsfälle geben, in denen global notwendig ist, sonst wäre es wohl kaum in der Sprache drin.
Könnte mir vielleicht jemand ein entsprechendes Beispiel zeigen?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Karl hat geschrieben:Ich hab mal eine Frage ... Wozu gibt es denn global, wenn man es nicht benutzen soll?
Ich weiß warum global (in den Fällen die ich kenne) nicht sinnvoll ist.
Aber dann muss es ja irgendwelche Anwendungsfälle geben, in denen global notwendig ist, sonst wäre es wohl kaum in der Sprache drin.
Nein, es gibt keine Fälle wo es notwendig wäre. Es ist halt einfach drin weil das mal eingefügt wurde (damals sah das Scoping von Python auch noch etwas anders aus) als man sich noch nicht so viele Gedanken gemacht hat wie sauberer Code ausschaut. Und seit dem ists eben dringeblieben, da wohl einiges an Code kaputtgehen würde der das eben nutzt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wobei man im Zuge von Python 3 IMHO durchaus etwas in die Richtung hätte machen können wollen dürfen sein.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

"Global" ist eben die "einfache", alte Art zu programmieren. Man hat ein paar Funktionen und diese greifen alle auf globale Daten zu und veränderen diese wann immer es nötig ist. Das ist ein recht einfaches und auch recht intuitives Konzept, deswegen war es auch das erste das man genutzt hat (in Sprachen wie C). So kann man programmieren. In der Regel macht man das heute nicht mehr so, sondern benutzt fortgeschrittenere Konzepte, wie Klassen, Closures, Iteratoren und Generatoren usw. All das kann alle Anwendungsfälle von globalen Daten ziemlich gut ausmerzen. Für spezielle Fälle (Ich kenne keinen) (oder für die schnelle Lösung) kann global nützlich sein, man sollte sich aber immer genau wissen, was man sich damit noch alles ins Boot holt/holen kann. Da Anfänger aber weder diese fortgeschritteneren Konzepte gut kennen (und grade deswegen intuitive Dinge wie global passender erscheinen) noch die nötige Erfahrung haben, um zu wissen, was wann einzusetzen ist, sagt man ihnen in der Regel, sie sollen global erstmal vergessen. Das gleiche mit eval() / exec: eval() ist recht intuitiv und man kann damit (als Anfänger) mit all dem, was man bereits weis, schnell zum Erfolg gelangen. Typisches Beispiel: Der Versuch, neue Variablen mit eval() zu Erzeugen und durchzunummerieren, obwohl das ein Einsatzort für eine Liste wäre. Deswegen sollen Anfänger auch eval() erstmal "vergessen". Auch eval() kann nützlich sein, nur eben nicht für die Fälle, die ein Anfänger typischerweise in Betracht ziehen würde. Aber grade wegen dieser Intuitivität sind beide Konzepte wichtig.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

str1442: Also hätte man global für 3.0 gut entfernen können, im Gegensatz zu eval(). Vermutlich hätte man besser auch die __del__()-Methode entfernt, anstatt sie nur in der Doku mit einem fetten roten Balken zu versehen.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?

Code: Alles auswählen

In [1]: class Foo(object):
   ...:     def __del__(self):
   ...:         print '__del__() was called'
   ...:         
   ...:         

In [2]: foo = Foo()

In [3]: del foo
__del__() was called

In [4]: foo = Foo()

In [5]: bar = foo

In [6]: del foo

In [7]: del bar
__del__() was called

In [8]: foo = Foo()

In [9]: foo = 'spam'
__del__() was called
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

snafu hat geschrieben:Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?
Lies doch die Doku und vor allem den fetten roten Balken der angesprochen wurde.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

snafu hat geschrieben:Wobei man im Zuge von Python 3 IMHO durchaus etwas in die Richtung hätte machen können wollen dürfen sein.
Stattdessen wurde die bisherige "Richtung" durch die nonlocal-Anweisung eher noch ausgebaut.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

@Karl: Eine Anwendungsmöglichkeit wäre, ein Modul als Singleton-Objekt zu verwenden.
snafu hat geschrieben:Wobei man im Zuge von Python 3 IMHO durchaus etwas in die Richtung hätte machen können wollen dürfen sein.
Nein wozu? global ist gut und praktisch, wenn man es braucht. Auf jeden Fall besser als direkt auf das Modul zuzugreifen. Da fängt der Spaß nämlich erst an.

Code: Alles auswählen

# coding: utf-8
# Modul: foo.py

import foo
bar = 0

def set_bar(x):
    foo.bar = x

if __name__ == '__main__':
    set_bar(23)
    print type(bar)
    
print 'Hi, ich werde zweimal ausgeführt, wenn man mich direkt aufruft'
Und man muss nicht gleich alles abschaffen, was problematisch sein könnte. Sonst kann man gleich Java nehmen.
snafu hat geschrieben:Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?
Nein, __del__ wird aufgerufen, wenn das Objekt vom garbage-collector beseitigt wird. Wenn der Intepreter beendet wird muss das nicht passieren, und falls __del__ dann doch aufgerufen wird, kann es sein, dass einige globale Variablen schon gelöscht wurden, die man dann nicht von __del__ aus benutzen sollte. Zusätzlich kann die Existenz von __del__ bei zirkulären Referenzen verhindern, dass das Objekt vom gc beseitigt wird. Ich glaube das war jetzt alles. Wenn man das alles beachtet, ist __del__ recht unproblematisch. ;)
Zuletzt geändert von Darii am Freitag 17. Juli 2009, 08:42, insgesamt 1-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Leonidas hat geschrieben:
snafu hat geschrieben:Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?
Lies doch die Doku und vor allem den fetten roten Balken der angesprochen wurde.
Da wird vor den Umständen gewarnt, die zu möglicherweise unerwartetem Verhalten führen können. Die Frage war aber, ob `__del__()` immer aufgerufen wird, sobald keine Referenz mehr auf das Objekt besteht. So lese ich das zumindest.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Darii hat geschrieben:Wenn man das alles beachtet, ist __del__ recht unproblematisch. ;)
Ja, steht ja bis auf die Sache mit dem Interpreter eigentlich alles in der Doku zu `__del__()` bzw `gc`. Ich wollte ja auch nicht andeuten, dass `__del__()` im "normalen" Gebrauch sinnvoll ist (vor allem `del != __del__()`), aber vielleicht will man ja in seltenen Fällen wissen, wann alle Referenzen auf ein Objekt weg sind. War jetzt auch mehr aus Interesse, weil ich mich in letzter Zeit ein bißchen mit Pythons C-Unterbau beschäftige.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

snafu hat geschrieben:Ja, steht ja bis auf die Sache mit dem Interpreter eigentlich alles in der Doku zu `__del__()` bzw `gc`.
Lies die Doku, das steht da. ;)
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Darii hat geschrieben: Zusätzlich kann die Existenz von __del__ bei zirkulären Referenzen verhindern, dass das Objekt vom gc beseitigt wird.
Nicht nur "kann". Die Existenz von `__del__()` in zirkulären Referenzen wird, zumindest in CPython, mit Garantie verhindern, dass die Referenz jemals aufgelöst wird, folglich werden diese beiden Objekte niemals aufgeräumt werden.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
TiKaey
User
Beiträge: 84
Registriert: Montag 24. November 2008, 20:48

Ich habe so das Gefühl, dass ich eine bzw zwei Ausnahmen der Art habe bei mir. Zumindest weiß ich nicht, wie ich es anders hinbekommen sollte.

Habe ja mal den Player gebastelt, der mittels mplayer einen Stream inkusive Benutzerzugangsdaten ansteuert.
Derzeit habe ich es so gemacht, dass ich mit einer bösen *g* globalen Variable überprüfe, ob der mplayer noch läuft, indem ich bei allen Funktionen wo der Abbruch davon kommen könnte eben jene Variable auf True setze. Anhand dessen wird dann woanders weiter verfahren.
Das zieht sich allerdings durch ein paar Funktionen hin.
Oder bei den Bindings, denen ich bestimmte Werte noch nicht mitgeben kann, weil sie erst überprüft werden müssen, nachdem das Event ausgelöst wurde, bzw. aufgrund von Angaben dann entsprechend behandelt werden.
Zumindest bin ich da noch nicht drauf gekommen.

Vielleicht stelle ich den Code mal ins Forum... muss nur erst einige Sachen rausnehmen bzw. anonymisieren. ;o) Und dann wird er eh zerissen, da bin ich mir schon sicher. *g*
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ein Zerreißen von Code ist aber eigentlich immer konstruktiv gemeint. Man kann auch froh sein, dass sich Leute die Zeit nehmen, den (oft wirklich üblen) Code durchzusehen und Verbesserungsvorschläge zu machen. Ich hab da z.B. eher selten Lust drauf.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Irgendwie hat noch niemand die ursprüngliche Frage beantwortet. Warum gibt es die `global`-Anweisung. Dabei ist die Antwort einfach. Python erfordert es nicht, Variablen vor ihrer Benutzung deklarieren zu müssen. Variablen in einer Funktion gelten immer als lokal in dieser Funktion. Hat man folgenden Code, so kann man die Variable außerhalb der Funktion deshalb nicht erreichen:

Code: Alles auswählen

a = 0
def f():
    a = 3
Möchte man, dass eine Zuweisung an eine Variable innerhalb einer Funktion nicht eine neue lokale Variable erschafft, sondern eine äußere globale Variable referenziert, so muss man dies mit `global` tun:

Code: Alles auswählen

a = 0
def f():
    global a
    a = 3
Hinweis: Globale Variablen, die man nicht verändern will, erfordern kein `global`. Sie sind, sofern nicht durch eine gleichnamige lokale Variable überschattet, immer erreichbar.

Stefan
Antworten