Closure Variablen bzw. Blockscoping

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.
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

Wieder viel gelernt! :) Zwar hab ich jetzt 10 neue Fragen aber, die stelle ich vielleicht lieber erst wenn ich wieder aus dem Urlaub zurück bin, meine Frau erwartet dass ich jetzt die Koffer packe.

VIELEN DANK
Kurt
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

sma hat geschrieben:Was ich mich ja schon immer gefragt habe: Python kann freien Variablen in einer Funktion keinen neuen Wert zuweisen, aber dennoch gibt es den Bytecode STORE_DEREF, der doch genau dieses machen könnte. Oder verstehe ich da etwas falsch?
Richtig. Den opcode gibts, aber die Syntax nicht. Wenn du brav bist und lieb nachfragst gibts vielleicht einen future import für nonlocal :-)
TUFKAB – the user formerly known as blackbird
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Ist doch schon angekündigt ;)
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

mitsuhiko hat geschrieben:
Was heißt hier neu binden ? Ints sind in Py keine Primitiva sondern eine Art Objekt ???
Neu binden heißt "name = wert". Damit wird name neu gebunden. Und ja, ints sind Objekte vom typ int. In Python ist alles ein Objekt.
so habe nun in ner Bahnhofsbuchhandlung kurz in einen O'Reilly reinschauen können und beginne das Konzept zu verstehen, der Punkt scheint zu sein das Python-Variablen per default lokal sind. Geschieht eine Zuweisung auf eine neue Variable, dann wird sie im aktuellen lokalen Namespace (Funktionsscope) angelegt, bzw. gebunden. Deswegen kann nicht schreibend auf eine Variable im closurekontext zugegriffen werden, weil eine neue lokale angelegt wird.

Korrekt?
mitsuhiko hat geschrieben: Im übrigen darfst du nicht mit deiner Vorstellung von Perl auf Python zurennen weil das überaus schmerzhaft wird.
Du ich kennen so manche Sprache, default local, sodass man nicht mehr schreibend auf nonlocal zugreifen kann, hab ich noch nie gesehen und ist IMHO der Erwähnung Wert.

Wir können gerne hier Javascript als Lingua Franca nehmen, Ruby kenne ich nur theoretisch (und im wesentlichen beschränkt auf sein Perl-Erbe.)

(BTW es kann nicht die eine Perl-Vorstellung geben, mit der man losrennen kann, weils eine Ansammlung unterschiedlicher Vorstellungen sind [z.B. zwei diametral unterschiedliche Variablentypen] Bei Python hingegen wird ja immer das Orthogonale, Homogene und Einfache gelobt, um die Reaktionen schonmal vorweg zu nehmen.)


Memoryleaks entstehen meines Wissens wenn die Garbage Collection eine Variable nicht entsorgen kann, weil die Variable nur anscheinend noch gebraucht wird. Z.B. bei Ringbezügen

Code: Alles auswählen

javascript:
var b=["B"];
var a=["A"];
a[1]=b;
b[1]=a;
alert(a[1][1][1]);


Die Arrays a und b sind gleichzeitig in Gebrauch und können deswegen nicht ohne weiteres von der GC abgeräumt werden => Memoryleak!

Wie Python das vermeiden soll, habe ich nicht verstanden. Variablen aus umhüllenden Kontexten sind zumindest in Perl nicht problematisch, weil eine Closurefunktion nur eine Referenz zum Namespace des Kontextes mitgeschleppt, wo bei Bedarf nachgeschaut wird und nicht eine komplette Kopie der Variablentabelle. Das JS es anders macht wäre mir auch komplett neu und unverständlich...
Zuletzt geändert von Kurt Z am Donnerstag 22. Mai 2008, 01:15, insgesamt 1-mal geändert.
BlackJack

CPython hat eine automatische Speicherbereinigung, die schaut ob Objekte noch durch eine aktive Referenz erreichbar sind. Wenn also ein Ring nicht mehr irgendwo, auch indirekt, an einen Namen gebunden ist, können alle Objekte im Ring entsorgt werden. So entsteht kein Speicherleck, aber die Freigabe geschieht bei Ringen verzögert.

Ist im Grunde wie bei Java und AFAIK auch bei .NET.
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

danke ich bin wieder schlauer offenbar hat Python ein zweistufigen GC, neben der Refrencecounter-Methode läuft in Intervallen ein Mark&Sweep.

Allerdings verstehe ich die Kausalität zwischen Memory Leaks und Blockscopes immer noch nicht.

Naja morgen fliegen wir weiter und ich hab 3 Wochen Internet-Entzug ... :D
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Kurt Z hat geschrieben:Allerdings verstehe ich die Kausalität zwischen Memory Leaks und Blockscopes immer noch nicht.
In Ruby/JavaScript lässt der Interpreter alle übergeordneten Frames im Speicher, selbst wenn die Variablen dort nicht genutzt werden. In Python erkennt der Intepreter, welche Variablen tatsächlich referenziert werden und nur diese bleiben in den cell-vars gespeichert. Wenn du nicht auf self zugreifst stirbt dann zb die Klasse.

Das hier zeigt das ganz gut:

Code: Alles auswählen

>>> class Foo(object):
...  def make_closure(self, num):
...   return lambda: num
... 
>>> foo = Foo()
>>> funcs = map(foo.make_closure, range(10))
>>> sys.getrefcount(foo)
2
In Ruby kann ich leider vom GC keine Refernzen finden lassen, aber es wären 11 auf foo weil jede Closure via self auf die Instanz zugreift. Das merkt man sehr schnell, wenn man mit Blocks anfängt selber auf Klassen oder Instanzen rumzupatchen und die Anwendung plötzlich einen Speicherverbrauch von nix Gutem hat. Das Problem tritt vor allem in vielen Rails Anwendungen auf, kann man wunderbar nach googlen :)
TUFKAB – the user formerly known as blackbird
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Memoryleaks entstehen meines Wissens wenn die Garbage Collection eine Variable nicht entsorgen kann, weil die Variable nur anscheinend noch gebraucht wird. Z.B. bei Ringbezügen
Dies ist so falsch bzw. nur richtig für reference counting, was kein echter garbage collection Algorithmus ist. Diese (z.B. die Klassiker stop&copy oder mark&sweep) haben mit Ringbezügen keine Probleme.

Stefan
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Speicherlecks entstehen meines Wissens, wenn ein Progammierer unabsichtlich Referenzen auf Objekte belässt und davon ausgeht, wieder eine saubere Ausgangslage für den nächsten Schritt zu haben. Das gilt sowohl für Implementierungen von Programmiersprachen als auch Programmen selbst.

Ich kann mir gut vorstellen, dass man auch in Python Speicherlecks (im Sinne von Programmen, die mit zunehmender Laufzeit immer mehr Speicher benötigen) schaffen kann, wenn man sich Mühe gibt ;)

OTOH, IANALowlevel-Experte.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Y0Gi hat geschrieben:Speicherlecks entstehen meines Wissens, wenn ein Progammierer unabsichtlich Referenzen auf Objekte belässt und davon ausgeht, wieder eine saubere Ausgangslage für den nächsten Schritt zu haben. Das gilt sowohl für Implementierungen von Programmiersprachen als auch Programmen selbst.
Sowas z.B. http://developers.slashdot.org/article. ... 17/0552247 :) Ist zwar kein Python, aber genau das Problem auf das du anspielst.
Antworten