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?
global?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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.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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
"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.
- 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.
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
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Lies doch die Doku und vor allem den fetten roten Balken der angesprochen wurde.snafu hat geschrieben:Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Stattdessen wurde die bisherige "Richtung" durch die nonlocal-Anweisung eher noch ausgebaut.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.
@Karl: Eine Anwendungsmöglichkeit wäre, ein Modul als Singleton-Objekt zu verwenden.
Und man muss nicht gleich alles abschaffen, was problematisch sein könnte. Sonst kann man gleich Java nehmen.
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.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.
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'
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.snafu hat geschrieben:Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?
Zuletzt geändert von Darii am Freitag 17. Juli 2009, 08:42, insgesamt 1-mal geändert.
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.Leonidas hat geschrieben:Lies doch die Doku und vor allem den fetten roten Balken der angesprochen wurde.snafu hat geschrieben:Verstehe ich den Hinweis in der Doku richtig, dass `__del__()` immer dann aufgerufen wird, wenn das Objekt nicht mehr referenziert wird?
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 hat geschrieben:Wenn man das alles beachtet, ist __del__ recht unproblematisch.
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.Darii hat geschrieben: Zusätzlich kann die Existenz von __del__ bei zirkulären Referenzen verhindern, dass das Objekt vom gc beseitigt wird.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
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*
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*
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.
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:
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:
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
Code: Alles auswählen
a = 0
def f():
a = 3
Code: Alles auswählen
a = 0
def f():
global a
a = 3
Stefan