Was muss ich in Python 3 importieren, damit es print kennt?
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
In Python zwei hat es funktioniert, aber in Python 3 bekomme ich für die Funktion print folgende Fehlermeldung: Exception NameError: "global name 'print' is not defined"
Muss ich da etwas Bestimmtes importieren, damit python3 print kennt?
Muss ich da etwas Bestimmtes importieren, damit python3 print kennt?
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Code: Alles auswählen
%> python3
Python 3.4.3+ (default, Jul 28 2015, 13:17:50)
[GCC 4.9.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("hallo alfons")
hallo alfons
Code: Alles auswählen
>>> del print
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'print' is not defined
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Danke, jetzt habe ich es nochmals ausprobiert. Print alleine geht schon. Aber in der Form geht es nicht:jens hat geschrieben:http://python3porting.com/noconv.html#s ... t-function
Code: Alles auswählen
class myprint(object):
def __del__(self):
print('Destroyed')
todestroy = myprint()
Ich glaube ich weiss jetzt, wie ich es richtig machen muss. Dauert nur ein wenig.
@Alfons Mittelmeyer: Lass die Finger von der `__del__()`-Methode. Die ist *nicht* nützlich für Dich. Falls man die tatsächlich mal braucht, dann sollte man genau wissen wie die Speicherverwaltung mit dieser Methode zusammenarbeitet, unter anderem auch welche Garantien einem Python bietet welche Objekte und Namensräume zum Zeitpunkt des Aufrufs zur Verfügung stehen und welche bereits weg sein können. Also zum Beispiel hätte Dich das jetzt nicht überraschen dürfen das eine Funktion wie `print()` nicht mehr existieren muss wenn `__del__()` aufgerufen wird. Du hast mehrfach demonstriert das Du hier keine Ahnung hast und auch nicht haben willst.
Bitte fang jetzt nicht wieder eine Diskussion mit Argumenten an die Du anderswo schon gebracht hast. Ich schaue mir diese sinnlosen Wiederholungen nicht lange an. Die bringen keinen weiter, kosten unnötig Zeit, und Du vermittelst neuen Lesern falsche, wirklich *falsche* Vorstellungen davon wie Speicherverwaltung in Python zu handhaben ist.
Bitte fang jetzt nicht wieder eine Diskussion mit Argumenten an die Du anderswo schon gebracht hast. Ich schaue mir diese sinnlosen Wiederholungen nicht lange an. Die bringen keinen weiter, kosten unnötig Zeit, und Du vermittelst neuen Lesern falsche, wirklich *falsche* Vorstellungen davon wie Speicherverwaltung in Python zu handhaben ist.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Sorry Ich lasse die Finger weg von del. Siehst Du doch. Jetzt auch geschafft für Python3:BlackJack hat geschrieben:@Alfons Mittelmeyer: Lass die Finger von der `__del__()`-Methode. Die ist *nicht* nützlich für Dich. Falls man die tatsächlich mal braucht, dann sollte man genau wissen wie die Speicherverwaltung mit dieser Methode zusammenarbeitet, unter anderem auch welche Garantien einem Python bietet welche Objekte und Namensräume zum Zeitpunkt des Aufrufs zur Verfügung stehen und welche bereits weg sein können. Also zum Beispiel hätte Dich das jetzt nicht überraschen dürfen das eine Funktion wie `print()` nicht mehr existieren muss wenn `__del__()` aufgerufen wird. Du hast mehrfach demonstriert das Du hier keine Ahnung hast und auch nicht haben willst.
Bitte fang jetzt nicht wieder eine Diskussion mit Argumenten an die Du anderswo schon gebracht hast. Ich schaue mir diese sinnlosen Wiederholungen nicht lange an. Die bringen keinen weiter, kosten unnötig Zeit, und Du vermittelst neuen Lesern falsche, wirklich *falsche* Vorstellungen davon wie Speicherverwaltung in Python zu handhaben ist.
foo.py:
Code: Alles auswählen
class Foo(object):
def __del__(self):
print('Collected')
f = Foo()
Code: Alles auswählen
import gc
from copy import copy
def destroy(a):
c = copy(a)
for k,e in c.items():
if k != '__builtins__': a.pop(k)
def start():
for _ in range(10):
a = {}
eval(compile(open('foo.py', "rb").read(), 'foo.py', 'exec'), a)
destroy(a)
print(gc.collect(), len(gc.garbage))
Code: Alles auswählen
python3
import collect
collect.start()
@Alfons Mittelmeyer: Nein, nicht alles richtig gemacht, sondern alles falsch, weil Du immer noch versuchst Probleme zu lösen die es nicht gibt.
Die `destroy()`-Funktion ist sinnlos, da sie nach aussen keinen Effekt hat.
In diesem Fall würde ich sagen das `pop()` ”verboten” ist, denn das ist nicht der offensichtliche Weg ein Schlüssel/Wert-Paar aus einem Wörterbuch zu entfernen. Wenn der Rückgabewert von `pop()` nicht verwendet wird, dann ist das semantisch der falsche Weg. Dafür gibt es nämlich ``del``. Da Du aber immer noch versuchst Speicher manuell zu verwalten, wie man an den Aufrufen von `gc`-Funktionen sieht, ist der Code unsinnig. Und mit dieser Speicherverwaltungsgeschichte nähert sich dieses Thema auch schnell dem gesperrt-werden.
Die `destroy()`-Funktion ist sinnlos, da sie nach aussen keinen Effekt hat.
In diesem Fall würde ich sagen das `pop()` ”verboten” ist, denn das ist nicht der offensichtliche Weg ein Schlüssel/Wert-Paar aus einem Wörterbuch zu entfernen. Wenn der Rückgabewert von `pop()` nicht verwendet wird, dann ist das semantisch der falsche Weg. Dafür gibt es nämlich ``del``. Da Du aber immer noch versuchst Speicher manuell zu verwalten, wie man an den Aufrufen von `gc`-Funktionen sieht, ist der Code unsinnig. Und mit dieser Speicherverwaltungsgeschichte nähert sich dieses Thema auch schnell dem gesperrt-werden.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Das Thema ist zuende, denn es ist vollbracht!BlackJack hat geschrieben:@Alfons Mittelmeyer: Nein, nicht alles richtig gemacht, sondern alles falsch, weil Du immer noch versuchst Probleme zu lösen die es nicht gibt.
Die `destroy()`-Funktion ist sinnlos, da sie nach aussen keinen Effekt hat.
In diesem Fall würde ich sagen das `pop()` ”verboten” ist, denn das ist nicht der offensichtliche Weg ein Schlüssel/Wert-Paar aus einem Wörterbuch zu entfernen. Wenn der Rückgabewert von `pop()` nicht verwendet wird, dann ist das semantisch der falsche Weg. Dafür gibt es nämlich ``del``. Da Du aber immer noch versuchst Speicher manuell zu verwalten, wie man an den Aufrufen von `gc`-Funktionen sieht, ist der Code unsinnig. Und mit dieser Speicherverwaltungsgeschichte nähert sich dieses Thema auch schnell dem gesperrt-werden.
Aber das verstehe ich wirklich nicht. Zuerst schreibst Du immer dass man del nicht benutzen darf, jetzt aber, dass ich es benutzen hätte sollen. Wer soll daraus noch schlau werden?
Und nach außen keinen Effekt soll die destroy Funktion haben? Sie löscht nur alles raus, was im Namespace ist. Viel besser als del für eine Funktion. Jetzt nämlich gleich alles und ganz ohne del.
@Alfons Mittelmeyer: Man soll ``del`` nicht benutzen um manuell Speicher verwalten zu wollen, ganz einfach weil das nicht funktioniert. Zum löschen von Namen weil man einen Namen aus einem Namensraum weg haben möchte, oder beispielsweise zum entfernen eines Schlüssel/Wert-Paares aus einem Wörterbuch, kann man es natürlich verwenden, weil es *dafür* ja auch *vorgesehen* ist.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Aber das ist ja dasselbe. Die Schlüsselwertpaare sind ja die globalen Variablen, Funktionen und Objekte. Und wenn ich jetzt del gemacht hätte, dann wäre es ja das Gleiche gewesen, was Ihr vorher so kritisiert hattet.BlackJack hat geschrieben:@Alfons Mittelmeyer: Man soll ``del`` nicht benutzen um manuell Speicher verwalten zu wollen, ganz einfach weil das nicht funktioniert. Zum löschen von Namen weil man einen Namen aus einem Namensraum weg haben möchte, oder beispielsweise zum entfernen eines Schlüssel/Wert-Paares aus einem Wörterbuch, kann man es natürlich verwenden, weil es *dafür* ja auch *vorgesehen* ist.
Also Sinn ergibt das keinen. Wenn man Funktionen mit del löscht, ist es verboten. Wenn man sie aber über ein Dictionary mit del löscht, dannn darf man das wieder.
@Alfons Mittelmeyer: Wenn Du versuchst mit ``del`` auf einem Wörterbuch *Speicherverwaltung* zu betreiben, dann ist es natürlich ”verboten”. Es verbietet sich von selbst weil das nicht funktioniert. Nur Du willst das einfach nicht wahrhaben. Weshalb das hier echt nervt. Und die `destroy()`-Funktion zeigt wieder mal das Du nicht weisst was Du da tust. Da ist es egal ob man `pop()` oder ``del`` verwendet, weil die wirklich absolut sinnfrei ist und *nichts* bewirkt ausser Rechenzeit zu verwenden.
@Alfons Mittelmeyer: hättest Du verstanden, von was wir hier die ganze Zeit reden, wärst Du gar nicht auf die Idee gekommen, del durch pop zu ersetzen, das ist so als ob Du blaue Smarties durch braune Smarties ersetzt. Noch skurriler finde ich ja das copy. Du willst hier manuelle Speicherverwaltung machen, verhinderst diese aber dadurch, dass Du eine Kopie machst.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Die Kopie ist lokal definiert und wird daher bei Ende der Funktion automatisch beseitigt. Und diese Kopie wird benötigt, damit ich aus dem Originaldictionary rauslöschen kann. Solange ich in einer Schleife über ein Dictionary bin, darf ich nämlich aus dem Dictionary nichts löschen. Daher die Kopie.Sirius3 hat geschrieben:@Alfons Mittelmeyer: hättest Du verstanden, von was wir hier die ganze Zeit reden, wärst Du gar nicht auf die Idee gekommen, del durch pop zu ersetzen, das ist so als ob Du blaue Smarties durch braune Smarties ersetzt. Noch skurriler finde ich ja das copy. Du willst hier manuelle Speicherverwaltung machen, verhinderst diese aber dadurch, dass Du eine Kopie machst.
Und von Speicherverwaltung habt Ihr anscheinend Null Ahnung. Es gibt Programme an denen hunderte von Programmierer arbeiten, die einige Millionen Zeilen von Quellcode haben und da sind die Prinzipien korrekter Speicherverwaltung genau zu beachten. Und wenn Ihr da arbeiten würdet und auf Euren skurrilen Ansichten über Speicher freigeben beharren würdet, bliebe nichts übrig als Euch gleich wieder rauszuwerfen.
Was soll denn dieser Unsinn wieder: wenn man große Datenmengen als Eintrag in eine Liste abspeichert oder in ein Dictionaty, darf man diesen Eintrag wieder löschen, sogar mit Del. Wenn man dafür aber eine Variable dynamisch anlegt, dann darf man die nicht wieder löschen, sondern muß sie im Speicher behalten, weil man hier kein Del benutzen darf? Und wenn dann andere Module auch viel Speicher brauchen, dann eben Crash. Es ist die Pflicht jedes professionellen Programmierers, dynamisch belegten Speicher wieder freizugeben und normalerweise nimmt man den dafür vorgesehenen Befehl, der in C++ etwa free heißt und bei Python del. Für Pipifax Desktop Anwendungen freilich, braucht man so etwas nicht.
Und Ihr wollt mir vorschreiben, dass hier schlampig programmieren Pflicht ist und korrekt programmieren verboten?
Oder muß man statt del Neuzuweisung nehmen?
Code: Alles auswählen
def function():
xxxx
xxxx
function()
function = None
Im Prinzip ist so eine Neuzuweisung dasselbe wie etwa in C++:
Code: Alles auswählen
# das soll verboten sein, weil man es nicht benutzen darf?
free Variable
#das allerdings ist erlaubt, weil man da free nicht benutzt hat? Bei C++ muss man diese Zuweisung allerdings in zwei Zeilen schreiben:
free Variable
Variable = None
Code: Alles auswählen
VAR['myfunction'](par1, par2, par3)
del VAR['myfunction']
Die destroy Funktion habe ich jetzt verbessert, denn man braucht kein deep copy und darf anscheinen hier schon del nehmen:
[Code=python file=Untitled.py]def destroy(a):
c = dict(a)
for k,e in c.items():
if k != '__builtins__': del a[k]
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 16. August 2015, 10:57, insgesamt 1-mal geändert.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Du willst halt auf biegen und brechen den Speicher selbst verwalten.
Somit sind alle sprachen die das nicht ermöglichen, weil sie es automatisch machen, nichts für dich.
Also, entweder du hörst damit auf, oder du must eine andere Sprache nehmen.
Somit sind alle sprachen die das nicht ermöglichen, weil sie es automatisch machen, nichts für dich.
Also, entweder du hörst damit auf, oder du must eine andere Sprache nehmen.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Jede Sprache verwaltet den Speicher automatisch. So werden lokale Variablen wieder gelöscht. Globale Variablen werden aber nicht gelöscht. Das muß man in jeder Programmiersprache selber machen. Python macht das genauso wenig. Und wenn man große Datenmengen in einem Modul lädt, die man nur temporär braucht und im Speicher läßt, und das bei noch anderen Modulen genauso macht, dann crasht das Programm bald. Lade einfach mal movies, etwa Spielfilme, mit verschiedenen Modulen und lass sie drinnen.jens hat geschrieben:Du willst halt auf biegen und brechen den Speicher selbst verwalten.
Somit sind alle sprachen die das nicht ermöglichen, weil sie es automatisch machen, nichts für dich.
Also, entweder du hörst damit auf, oder du must eine andere Sprache nehmen.
Weiß nicht ob marhal.load so etwas macht. Dass man damit etwa eine Movie von zwei Gigabyte in eine Variable laden kann, und ob die Variablen in Python so gross sein dürfen. Jedenfalls wenn man das ein paarmal hintereinander machen würde und jedesmal eine neue Variable benützt, ohne die vorige zu löschen.: lang macht man das jedenfalls nicht.
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 16. August 2015, 11:36, insgesamt 2-mal geändert.
Geh bitte. Du bist hier anscheinend falsch. ><((((*>Alfons Mittelmeyer hat geschrieben:Euren skurrilen Ansichten
Euch gleich wieder rauszuwerfen
Was soll denn dieser Unsinn wieder
Es ist die Pflicht jedes professionellen Programmierers
Für Pipifax Desktop Anwendungen freilich, braucht man so etwas nicht
Und Ihr wollt mir vorschreiben, dass hier schlampig programmieren Pflicht ist und korrekt programmieren verboten?
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Also beachtet bitte die Regel: del darf man für Einträge in dictionaries nehmen und für Einträge in Listen, sonst aber nicht.
Die richtige Art globale einzelne Definitionen zu löschen - also was man nicht in globale Listen oder globale Dictionaries eingetragen hat - ist daher diese:globals() ist allerdings nur der Namensraum für die Hauptanwendung.
Die richtige Art globale einzelne Definitionen zu löschen - also was man nicht in globale Listen oder globale Dictionaries eingetragen hat - ist daher diese:
Code: Alles auswählen
def myfunction(): pass
del globals()['myfunction']
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 16. August 2015, 12:08, insgesamt 1-mal geändert.
Du vermischt da einige Konzepte. In kompelierten Sprachen werden globale Variablen üblicherweise im `.data`-Segement abgelegt:Alfons Mittelmeyer hat geschrieben:Jede Sprache verwaltet den Speicher automatisch. So werden lokale Variablen wieder gelöscht. Globale Variablen werden aber nicht gelöscht.
Code: Alles auswählen
int x = 3;
static int y = 5;
void main(void) {}
Code: Alles auswählen
╭─dav1d@doom /tmp
╰─$ gcc global.c -o global
╭─dav1d@doom /tmp
╰─$ objdump -t global
global: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 init.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000401928 l O .jcr 0000000000000000 __JCR_LIST__
0000000000401930 l O .tm_clone_table 0000000000000000 __TMC_LIST__
0000000000400490 l F .text 0000000000000000 deregister_tm_clones
00000000004004d0 l F .text 0000000000000000 register_tm_clones
0000000000400510 l F .text 0000000000000000 __do_global_dtors_aux
0000000000401940 l O .bss 0000000000000001 completed.6938
0000000000401930 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry
0000000000400530 l F .text 0000000000000000 frame_dummy
0000000000401938 l O .init_array 0000000000000000 __frame_dummy_init_array_entry
0000000000000000 l df *ABS* 0000000000000000 global.c
0000000000401924 l O .data 0000000000000004 y
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
00000000004006d8 l O .eh_frame 0000000000000000 __FRAME_END__
0000000000401928 l O .jcr 0000000000000000 __JCR_END__
0000000000401918 l O .data 0000000000000000 .hidden __dso_handle
0000000000401930 l O .tm_clone_table 0000000000000000 .hidden __TMC_END__
0000000000401710 l O .dynamic 00000000000001d0 .hidden _DYNAMIC
0000000000401938 l .init_array 0000000000000000 .hidden __init_array_start
0000000000401940 l .init_array 0000000000000000 .hidden __init_array_end
00000000004018e8 l O .got.plt 0000000000000028 .hidden _GLOBAL_OFFSET_TABLE_
00000000004005d0 g F .text 0000000000000002 __libc_csu_fini
0000000000400460 g F .text 000000000000002a _start
0000000000400560 g F .text 0000000000000065 __libc_csu_init
0000000000400556 g F .text 0000000000000007 main
0000000000401910 w .data 0000000000000000 data_start
00000000004005e0 g O .rodata 0000000000000004 _IO_stdin_used
0000000000000000 F *UND* 0000000000000000 __libc_start_main
0000000000401910 g .data 0000000000000000 __data_start
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000400408 g F .init 0000000000000000 _init
00000000004005d4 g F .fini 0000000000000000 _fini
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w *UND* 0000000000000000 _Jv_RegisterClasses
0000000000401920 g O .data 0000000000000004 x
0000000000401940 g *ABS* 0000000000000000 _edata
0000000000401940 g *ABS* 0000000000000000 __bss_start
0000000000401941 g *ABS* 0000000000000000 _end
Code: Alles auswählen
0000000000401924 l O .data 0000000000000004 y
0000000000401920 g O .data 0000000000000004 x
Nun zu lokalen Variablen, diese werden auf einem Stack-Segement abgelegt, welches von dem Stack wieder "entfernt" wird sobald die der Scope verlassen wird.
Nun zur eigenltichen Speicherverwaltung, dem Heap, das "Gegenstück" zum Stack, welcher nicht automatisch wächst und Speicher nicht "automatisch" freigegeben werden wie beim Stack. Speicher der im Heap reserviert wird bleibt bestehen bis er wieder freigegeben wird. Man kann z.B. Speicher via `malloc` reservieren und wieder mit `free` freigeben, dann gibt es noch die Variante über einen Garbage Collector (von Jens angesprochen) Speicher zu reservieren, der GC kümmert sich darum dass Speicher wieder freigegeben wird sobald er nicht mehr benutzt wird (vereinfacht: er scannt den Speicherbereich nach Referenzen/Pointern, wenn er etwas findet dass in einen reservierten Bereich zeigt, wird der Speicher noch gebraucht und nicht freigegeben).
Python benutzt einen solchen Garbage Collector (gibts übrigens auch für C/C++, z.B. libgc). Also alles was du tust ist im Grunde dem Garbage Collector die Arbeit zu erschweren und machst es teilweise sogar schlimmer (z.B. das copy). Es kann durchaus Situationen geben in denen `del` Sinn macht, allerdings für jemanden wie dich, der nicht wirklich versteht was los ist mit Memory Management sollte die Finger davon lassen.
Fazit: Du verrennst dich da in Sinnlosem, wenn du wirklich ein low memory profile brauchst (also wirklich wirklich wirklich low), dann nimm nicht Python. Aber denke jetzt nicht, wusste ich doch gleich Python taugt nix, Garbage Collectoren sind scheiße. Python läuft ohne Probleme auf Micro-Controllern und ein guter Garbage Collector kann durchaus mal schneller und effizienter sein als manuelles Memory Management von einem der keine Ahnung hat wies geht .
PS: Wenn du versuchst Module zu entladen, das geht sowieso nicht wirklich: http://bugs.python.org/issue9072.
the more they change the more they stay the same
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Du vermischt da einige Konzepte. Statische globale Variablen werden im '.data' - Segment abgelegt. Bei dynamisch allokiertem Speicher werden nur die Pointer also die Verweise auf den Speicher im '.data' Segment abgelegt. Und der Speicher wird dann aus dem Heap allokiert, etwa:Dav1d hat geschrieben:Du vermischt da einige Konzepte. In kompelierten Sprachen werden globale Variablen üblicherweise im `.data`-Segement abgelegt:Alfons Mittelmeyer hat geschrieben:Jede Sprache verwaltet den Speicher automatisch. So werden lokale Variablen wieder gelöscht. Globale Variablen werden aber nicht gelöscht.
Code: Alles auswählen
# hier wird ein globaler Pointer myVar definiert, der im '.data' Segment als Verweis auf bisher nichts Brauchbares abgelegt wird.
# außerdem wird er als Pointer auf eine Klasse definiert, sodass er nur auf diese Klasse anwendbar ist
# (natürlich gibt es auch Möglichkeiten Pointer für beliebige Klassen zu verwenden mit Datentyp void und dann type casts)
MyClass * myVar = Null
# und hier findet dann die eigentliche Zuweisung statt, in der dann Speicher dynamisch allokiert wird
myVar = new MyClass(par1,par2,par3)
# und wenn der Speicher nicht freigegeben wird, bleibt dieser erhalten. Genauso ist es in Python. Zum Freigeben existiert der Befehl delete und in Python heißt er del
# Python hat allerdings eine Speicherverwaltung, die sich um Vieles kümmert, sodass man das del nicht explizit braucht, weil es in einigen Befehlen schon enthalten ist.
# wenn man in C++ nun das schreiben würde, wäre es verkehrt:
myVar = new MyClass(otherpar1,otherpar2,otherpar3)
# denn dadurch verursacht man ein Memory Leak, weil man jetzt neuen Speicher allokiert hat, ohne den alten freizugeben
# richtig daher:
delete myVar
myVar = new MyClass(otherpar1,otherpar2,otherpar3)
# In Python ist hier ein del völlig unnötig, wel das del bereits in der Zuweisung mit enthalten ist, genauso, wie etwa auch bei pop()
# Und wer hier del benutzt betreibt Mikroprogrammierung und hat von der Speicherverwaltung von Python nichts verstanden
Wie wir gesehen hatten, haben globale Pointer mit dynamisch allokiertem Speicher sehr wohl etwas mit Speicherverwaltung zu tun. Bei statischen Variablen bleibt allerdings der Speicher stets gleich und muss man sich nicht darum kümmern. Der Vorteil der Speicherverwaltung von Python ist, dass man sich normalerweise durch das in der Zuweisung und der pop-Funktion bereits enthaltene del, so ziemlich gar nicht um die Speicherverwaltung zu kümmern braucht. Stimmt natürlich nicht ganz, denn wer Daten in Listen und dergleichen speichert, da immer mehr hineinmüllt und sich nicht darum kümmert, dass etwas nur kurzzeitig gebraucht wurde, und glaubt, dass die Speicherverwaltung automatisch seinen Saustall aufräumt, der liegt verkehrt.Dav1d hat geschrieben:Also globale Variablen haben schonmal absolut nichts mit Speicherverwaltung zu tun (PS: ob die globale Variable mit static deklariert wurde oder nicht sieht man am `l` oder `g`).
Dav1d hat geschrieben:Nun zur eigenltichen Speicherverwaltung, dem Heap, das "Gegenstück" zum Stack, welcher nicht automatisch wächst und Speicher nicht "automatisch" freigegeben werden wie beim Stack. Speicher der im Heap reserviert wird bleibt bestehen bis er wieder freigegeben wird. Man kann z.B. Speicher via `malloc` reservieren und wieder mit `free` freigeben, dann gibt es noch die Variante über einen Garbage Collector (von Jens angesprochen) Speicher zu reservieren, der GC kümmert sich darum dass Speicher wieder freigegeben wird sobald er nicht mehr benutzt wird (vereinfacht: er scannt den Speicherbereich nach Referenzen/Pointern, wenn er etwas findet dass in einen reservierten Bereich zeigt, wird der Speicher noch gebraucht und nicht freigegeben).
Daraus besonders dieser Teil:
Ob der Speicher noch benutzt werden soll, weiss der gc nicht. Er weiss nur ob der Referenzzähler Null ist oder nicht - bzw. ob die Referenz noch beinen reservierten Speicherbereich zeigt. Also, ob etwas noch gebraucht wird, weiß der gc nicht und wenn jemand Objekte, die er nicht mehr braucht, nicht aufräumen will sondern einfach weiter ansammelt, dann wird eben der Speicher vollgemüllt, bis Python bedendet wird oder bis es einen Crash gibt. Und bei lang laufenden Programmen mit großen Datenbeständen, kommt es eben dann zu Crashs.der GC kümmert sich darum dass Speicher wieder freigegeben wird sobald er nicht mehr benutzt wird[/b] (vereinfacht: er scannt den Speicherbereich nach Referenzen/Pointern, wenn er etwas findet dass in einen reservierten Bereich zeigt, wird der Speicher noch gebraucht und nicht freigegeben).
Während lokale Variablen in Funktionen selber wieder beseitigt werden, werden globale Variablen nicht von selber aufgeräumt, sondern die Daten bleiben erhalten, bis man sie löscht. Warum man bei Einträgen in Listen und Directories dazu del nehmen darf, bei einzelnen Variablen dagegen nicht, bleibt ein Rätsel.
Anscheinend bin ich der einzige hier der etwas vom Memory Management versteht. Und solche wie Du sollten da einfach besser still sein. Vielleicht viel Bücher gelesen, verstanden aber offentlich nichts.Dav1d hat geschrieben:Python benutzt einen solchen Garbage Collector (gibts übrigens auch für C/C++, z.B. libgc). Also alles was du tust ist im Grunde dem Garbage Collector die Arbeit zu erschweren und machst es teilweise sogar schlimmer (z.B. das copy). Es kann durchaus Situationen geben in denen `del` Sinn macht, allerdings für jemanden wie dich, der nicht wirklich versteht was los ist mit Memory Management sollte die Finger davon lassen.
Ich brauche kein low memory profile aber ein grow and grow and grow memory profile ebensowenig. Und Python ist optimal geeignet, hervorragend. Ein guter Garbage Collector kann keinen Saustall aufräumen, weil jemand den Speicher vollmüllt. Ein manuelles Memory Management brauche ich nicht. Denn ich habe die destroy() Funktion geschrieben, die den Speicher leer räumt. Und wer überhaupt keine Ahnung hat, bist Du. Sonst hättest Du gemerkt, dass ich darüber gar nicht mehr dikutieren brauche, weil ich die Funktion habe, die automatisch nach Ablaufen eines Scripts, den vom Script verwendeten Speicher wieder löscht. Und um Module ging es auch nicht, sondern um Scripts.Dav1d hat geschrieben:Fazit: Du verrennst dich da in Sinnlosem, wenn du wirklich ein low memory profile brauchst (also wirklich wirklich wirklich low), dann nimm nicht Python. Aber denke jetzt nicht, wusste ich doch gleich Python taugt nix, Garbage Collectoren sind scheiße. Python läuft ohne Probleme auf Micro-Controllern und ein guter Garbage Collector kann durchaus mal schneller und effizienter sein als manuelles Memory Management von einem der keine Ahnung hat wies geht .
PS: Wenn du versuchst Module zu entladen, das geht sowieso nicht wirklich: http://bugs.python.org/issue9072.