BlackJack hat geschrieben:Falls Du Variablen als Kästen mit einem Namen ansiehst in die man einen Wert hinein tut, dann solltest Du dieses Bild ganz schnell aus dem Kopf verbannen! Das passende Bild für Python (und auch einige andere Programmiersprachen) sind Objekte auf die kleine Post-It-Zettel mit Namen geklebt werden. Eine Zuweisung nimmt also nicht etwas aus einer Box und tut es in eine andere, sondern es wird ein Zettel auf ein Objekt geklebt, der vorher eventuell auf einem anderen Objekt klebte.
Ist schon richtig, das Problem, das ich damit habe, ist ein logisches.
Wenn ich x als ein Ding betrachte und Teile dieses Dings verändere, dann würde ich erwarten, dass - bei copy on write - bei der Veränderung dieses Dinges eine neue Kiste mit dem alten PostIt angelegt wird. Tatsächlich passiert das aber nur durch explizite Zuweisung, also beispielsweise den Operator "=".
Beim Aufruf einer Funktion wird ebenfalls eine solche Zuweisung durchgeführt. Wenn ich in einer solchen Funktion Teile modifiziere, ohne/ehe erneut zuzuweisen, ändere ich damit zwangsläufig den übergebenen Wert. Bei einfachen Typen, wie integer und float- Typen spielt das keine Rolle, da es keine Funktionen gibt, diese zu modifizieren. Bei Veränderungen müssen sie erneut zugwiesen werden. Für den Aufrufenden ist der Hä- Effekt also gering. Wenn der Wert in der Funktion geändert wird, dann kommt auf die Änderung ein neues PostIt drauf, seine PostIts kleben immer noch auf Werten, die unverändert sind.
Selbst, wenn der Hintergrund ein anderer ist, resultierend wirkt es, wie eine Übergabe per Wert.
Sind die Variablen aber komplexer, also so, dass es Modifikationsmöglichkeiten gibt (Listen, Dictionaries, Klassen), dann klebt das PostIt auf einem Kästchen, dessen Inhalt sich ändert, OHNE dass ein neues PostIt angefangen wird.
Also nach dieser Sichtweise gibt es schon einen Unterschied.
Ich habe für mich noch keinen guten Weg gefunden, python- Code wiederverwendbar zu schreiben. Erklärung:
Code: Alles auswählen
#Modul A:
def a(x)...
#Modul B:
def b(x):
A.a(x)
#Modul C:
def c(x):
B.b(x)
Wenn ich b(x) schreibe, dann muss ich sowohl Annahmen treffen, für welche Sorte von Objekten ich funktionieren muss, ohne das so ohne Weiteres deklarieren zu können.
Die einzige Möglichkeit besteht darin, irgend etwas der Form
Code: Alles auswählen
if 'ABC' in dir(x) and (('DEF' in dir(x)) or ('EFG' in dir(x)):
...
else:
return None
zu machen.
Und selbst, wenn ABC, DEF oder EFG vorkommen, kann ich immer noch nicht wissen, ob sie mit den von mir erwogenen Parametern funktionieren
Und im Hinblick auf a(x) weiß ich zwar, welche Parameter ich übergeben kann oder muss, aber welchen Typ diese Parameter haben müssen (oder um mit Duck- Typing zu sprechen, welche Funktionen sie auf welche Weise implementieren müssen, bekomme ich auch nur heraus, wenn ich mich durch den Quellcode von a hangele.
Als b(x) muss ich also ausreichend flexibel sein, so dass ein an sich sehr kompakt zu schreibender Python- Code theoretisch durch jede Menge Fallunterscheidungen aufgebläht werden müsste in der Weise entweder
Code: Alles auswählen
def SchmutzBeseitigen(Zimmer):
if hatFunktion('Fegen'):
Zimmer.Fegen(heute)
elif hatFunktion('Wischen'):
Zimmer.Wischen(heute)
elif hatFunktion('Sprengen'):
Zimmer.Sprengen(heute)
else:
return 'Schmutz nicht entfernbar'
oder
Code: Alles auswählen
def SchmutzBeseitigen2(Zimmer):
ging = False
if not ging:
try:
Zimmer.Fegen(heute)
ging = True
except
pass
if not ging:
try:
Zimmer.Wischen(heute)
ging = True
except
pass
if not ging:
try:
Zimmer.Sprengen(heute)
ging = True
except
pass
if not ging:
return 'Schmutz nicht entfernbar'
wobei die letzte Variante den Charme hat, auch zu funktionieren, wenn die Funktion Sprengen vielleicht etwas anderes tut, als für ein Zimmer zu erwarten wäre.
Hat jemand diesbezüglich irgend eine Literaturempfehlung (und nein, es fängt nicht damit an, Variablen zu benennen oder Einrückungen zu beachten. Das ist trivial. Wie geht man damit um, auf ALLE Eventualitären an jeder Stelle gefasst sein zu müssen?
In meiner Vorstellung ist python quasi die Weiterentwicklung von Templates. Templates wurden geschaffen, damit man nicht für jeden Datentyp eigene Sortierroutinen, Stapel, Listen, Bäume schreiben muss. Allerdings habe ich den letzten 30 Jahren vielleicht 30 Klassen geschrieben, die im weitesten Sinne Templates waren. Bei dem Rest waren Klassen/Funktionen/Methoden etc. mit weit weniger Freiheitsgraden verbunden, weil sie Geschäftsprozesse beschrieben haben, die klar umrissen werden konnten.
Daher tue ich mich noch etwas schwer damit, effizient (nicht laufzeit- sondern entwicklungszeiteffizient mit Nachnutzung und so weiter) in python code zu schreiben.
Wo finde ich an dieser Stelle Hilfe, habt ihr eine Idee?