Zugriff auf dict von class aus gesehen

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.
Benutzeravatar
grubenfox
User
Beiträge: 432
Registriert: Freitag 2. Dezember 2022, 15:49

@blackjack: naja, Python-Anfänger könnten in der Python-Doku über das Modul stolpern und mit Arrays eben `array`-Arrays meinen. Hier bei Holzbein wohl nicht der Fall. Dass das Modul nur selten genutzt wird ist dann eine andere Geschichte.
Benutzeravatar
__blackjack__
User
Beiträge: 13119
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Holzbein: Selbst wenn man von SQLAlchemy nur den Core-Teil, also nicht den „object relational mapper“ (ORM) verwendet, ist das mehr als man normalerweise selber programmiert um SQL als Zeichenketten zusammenzubasteln. Es ist flexibler, leichter erweiterbar, und robuster/sicherer. Es ist nicht nur das man nicht mehr von einer konkreten Datenbank abhängig ist, sondern auch, dass das SQL syntaktisch nicht kaputt gehen kann. Man hat zusätzlich die Tabellendefinitionen und Beziehungen als Dokumentation.

Der Array-Begriff ist so eigentlich nur in PHP verbreitet. Das ist also in so ziemlich allen anderen Programmiersprachen etwas verwirrend Abbildungen von Schlüsseln auf Werte „Array“ zu nennen.

Das läuft bei Dir ohne die erste Zeile in der `__init__()`, denn wie gesagt bewirkt die nichts. Namen oder normale/einfache Attribute haben kein „Gedächtnis“ über Werte oder Typen die vorher mal daran gebunden waren und wenn man *direkt* hinterheinander zwei verschiedene Werte an einen Namen oder Attribut bindet, dann hat das den gleichen Effekt als wenn man nur die zweite Zuweisung alleine macht. Das wäre sonst auch *sehr* komisch. Was denkst Du denn was da magisches passieren würde bei der ersten Zuweisung?

@grubenfox: Das ist kein „call by reference“ in Python, denn dann würde eine Zuweisung an ein Argument die Bindung ausserhalb der Funktion ändern können. Und es ist auch kein „call by value“, denn dann würden die Werte beim Aufruf kopiert werden und Änderungen an Datenstrukturen wären beim Aufrufer nicht sichtbar. Es ist „call by (object) sharing“ — Aufrufer und Aufgerufener greifen über den Namen auf das *selbe* Objekt zu. Änderungen die der Aufgerufene vornimmt, sind beim Aufrufer sichtbar.

Wenn eine Sprache „call by reference“ macht oder zumindest die Option bietet, muss folgendes möglich sein, wie in diesem Pascal-Beispiel, wo „call by reference“ per VAR für das Argument deklariert wird:

Code: Alles auswählen

var a: Integer;

procedure DoSomething(var a: Integer);
begin
  a := 42;
end;

begin
  a := 23;
  DoSomething(a);
  WriteLn('a: ', a);  { Gibt 'a: 42' aus. }
end.
Oder in QBasic, wo „call by reference“ das normale Verhalten ist ist („call by value“ gibt es im grossen Bruder QuickBasic als Alternative und kann dort mit BYVAL deklariert werden):

Code: Alles auswählen

DIM a AS INTEGER
a = 23
DoSomething a
PRINT "a:"; a  ' Gibt "a: 42" aus.

SUB DoSomething (a AS INTEGER)
  a = 42
END SUB
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Holzbein
User
Beiträge: 9
Registriert: Freitag 16. Dezember 2022, 13:53

bwbg hat geschrieben: Samstag 17. Dezember 2022, 11:01 Die Beschreibung lässt den starken Verdacht zu, dass es auf deinem (öffentlichen) Webserver eine Schnittstelle gibt, die es erlaubt, beliebige SQL-Queries auf die Datenbank abzusetzen.
Na, ja, die Alarmglocken kannst wieder abstellen. ist natürlich abgesichert. SLQ String verschlüsselt und Übergabe Key. Also kein Prolem. Ganz so Blauäugig bin ich nicht ;)
grubenfox hat geschrieben: Samstag 17. Dezember 2022, 12:57 Also wenn es nicht eh schon klar wäre dass wir ein Problem haben.. dann jetzt: in Python ist die Übergabe immer per Reference und ich habe mal gelernt ein häufig gemachter Anfängerfehler sei, in Funktionen/Methoden übergebene veränderbare Datenstrukturen zu ändern um sich dann außerhalb der Funktionen/Methode zu wundern warum die Datenstrukturen auf einmal kaputt ist.
Wirklich by reference? Ich habe eher das Gefühl, das Pythen per value arbeitet wenigstens bei dictionaries. Sonst hätten wir das ganze Theater ja nicht - ob gut oder schlecht ist dann eine eigene Frage.
grubenfox hat geschrieben: Samstag 17. Dezember 2022, 12:57 Um das zu vermeiden mittels copy.deepcopy() eine Kopie der übergebenen Daten machen... falls nötig.. eventuell reicht auch copy.copy(). [Hier jetzt vielleicht nicht gewünscht.]
copy.deepcopy() brauche ich ja so und so, wenn ich eine Protype Struktur erzeuge und diese dann an mehreren Stellen einer anderen Struktur einkopieren möchte. Sonst werden nur referencen eingehängt und eine Änderung hier hat die Änderung dort zur Folge. wenn ich mich recht erinnere. Da bin ich auch schon mal drüber gestolpert.
grubenfox hat geschrieben: Samstag 17. Dezember 2022, 12:57 P.S.:
Holzbein hat geschrieben: Samstag 17. Dezember 2022, 09:57 Danke für die Zeit und die Ideen!
Schönen Sonntag noch.
Zum Glück haben wir noch Samstag! :D
:D - Danke!
Holzbein
User
Beiträge: 9
Registriert: Freitag 16. Dezember 2022, 13:53

__blackjack__ hat geschrieben: Samstag 17. Dezember 2022, 16:02 @Holzbein: Selbst wenn man von SQLAlchemy nur den Core-Teil, also nicht den „object relational mapper“ (ORM) verwendet, ist das mehr als man normalerweise selber programmiert um SQL als Zeichenketten zusammenzubasteln. Es ist flexibler, leichter erweiterbar, und robuster/sicherer. Es ist nicht nur das man nicht mehr von einer konkreten Datenbank abhängig ist, sondern auch, dass das SQL syntaktisch nicht kaputt gehen kann. Man hat zusätzlich die Tabellendefinitionen und Beziehungen als Dokumentation.
Geb die absolut Recht, und werde mir das definitiv anschauen. Vielleicht nicht sofort, aber sicher!


Array ist für mich ein Überbegriff für Strukturen, auch mehrdimendionale.
Und als erstes bin ich in python über die Array gestolpert, welche keinen Alphanumerischen key können. Und dann bin ich auf die Dictionaries gestoßen mit den Beispielcodes wie z.B.

self.Control_config=defaultdict(set) oder
self.Control_config=defaultdict(dict) oder
self.Control_config=defaultdict(int), was man halt benötigt.

die ich deshalb verwende.

Auch wenn das echt lästig ist, jeden Zweig, jede Dimmension so neu einrichten zu müssen.

Habe mich seit dieser Diskussion etwas weiter eingelesen und bin im Moment beim Umbauen. Mal schauen, wohin der Weg führt.

Aber ihr habt natürlich recht, genaue Begriffe ergeben genaue Fragen ergeben genaue Antworten.
Ich werde mich bessern - ist halt ein langer Weg. (vorallem bei dem Mischmasch der vielen Programm Sprachen)
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist nicht läßtig sondern schlicht überflüssig, weil Du Wörterbücher falsch benutzt. Was grubenfox geschrieben hat, ist zwar formal richtig, aber man schreibt normalerweise Programme so, das man nichts per `copy` kopiert. Wenn man das macht, macht man was falsch.
Was Du von neuen Sensorwerten und dem Erweitern von DB-Tabellen schreibst, läßt befürchten, dass Du tatsächlich Datenbanktabellen änderst, dann solltest Du noch Normalisierung von Tabellen auf Deinen Lehrplan setzen.
Benutzeravatar
grubenfox
User
Beiträge: 432
Registriert: Freitag 2. Dezember 2022, 15:49

@__blackjack__: ja, wo er recht hat,... (Danke dafür)
Als ich anfing mich mit diesem ganzen Kram zu beschäftigen, da gab es nur "call by value" und "call by reference". Solch 'neumodischen' ;-) Begriff wie "call by (object) sharing" gab es damals in meinem Umfeld nicht. Zu "call by reference" hatte ich gelernt: wenn ich etwas per "call by reference" an eine Funktion übergebe und es dann in der Funktion ändere, dann ist die Änderung hinterher auch außerhalb der Funktion sichtbar. Bei Python hatte ich gelernt: wenn ich z.b. eine Liste (oder ein Dict) an eine Funktion übergeben und es dann in der Funktion ändere, dann ist die Änderung hinterher auch außerhalb der Funktion sichtbar.

Deshalb wohl meine falsche Verbindung zwischen Python und "call by reference".

Es bleibt meine Verwunderung darüber dass Änderungen an einem Dict als Datenstruktur offenbar nicht überall durchschlagen, sondern nur lokal bleiben.
Holzbein hat geschrieben: Samstag 17. Dezember 2022, 08:10 Bis ich über das Orginalproblem stolperte, dass in gewissen Fällen in diesem Dict geänderte Daten dann in den Klassen/Methoden nicht geändert erscheinen.
Aber das lässt sich mit Funktionen in Modulen mit Parameterübergabe lösen.
(Das einfachste wäre Übergabe als reference, dann könnte die Datenstruktur direkt geändert werden, aber das spielts in Python nicht. :mrgreen: )
Ich kenne da in Python das Problem nur andersrum, dass Änderungen eben nicht lokal bleiben, sondern auch außerhalb von Funktionen/Methoden sichtbar sind. Irgendwo íst da etwas komisch...
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Du kannst gedanklich zunächst ruhig bei "call by reference" bleiben, falls es dir das Verständnis erleichtert. Denn es sind in Python stets Referenzen (aka. Labels), die als Argumente an Funktionen übergeben werden. Wichtig dabei ist zu wissen, dass diese Referenzen auf Objekte verweisen (die u.a. "wissen" wie häufig sie referenziert werden); dies ist es, was __blackjack__ als "call by (object) sharing" bezeichnet. Das weitere Verhalten wird durch die Eigenschaften der referenzierten Objekte bestimmt, z.B. ob diese mutabel oder immutabel sind.
Benutzeravatar
__blackjack__
User
Beiträge: 13119
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@grubenfox Ich weis gar nicht mehr so genau ob ich die Aufrufkonventionen „call by reference“ und „call by value“ zuerst auf dem C64 bei Comal oder auf dem PC bei Pascal kennengelernt habe. Ist jedenfalls auch lange her. Allerdings ist der Begriff „call by sharing“ von 1974. Also deutlich vor meinem Kontakt mit den anderen beiden Begriffen oder Computern überhaupt. Zu dem Zeitpunkt hatte ich wohl noch nicht mal Kontakt zu fester Nahrung. 🤣

Das was Du beschreibst ist nicht der wichtige Punkt bei „call by reference“. Der wichtige Punkt ist, dass man eine einfache Zuweisung beim Aufgerufenen machen kann, und die über den Namen beim Aufufer sichtbar ist, weil der Argumentname ein Alias für den Namen ist an den zugewiesen wird. Das ist etwas anderes als den Inhalt von Objekten zu verändern.

@kbr: Nein das wäre falsch, denn wie schon gesagt müsste mit dem Verständnis von „call by reference“ ja folgendes möglich sein:

Code: Alles auswählen

def do_something(a):
    a = 42


def main():
    a = 23
    do_something(a)
    print(a)  # Hier müsste 42 ausgegeben werden.
Das wäre „call by reference“ so wie man das aus Pascal, oder QBasic, oder auch C++ kennt, also so wie der Begriff halt definiert ist.

Das man auch von Referenzen auf Objekte spricht hat nichts mit der Semantik von „call by reference“ zu tun. Diese Begriffsverwirrung hat man “netterweise“ auch bei Java, wo man zwischen primitiven Typen und Referenztypen unterscheidet und die primitiven Typen „call by value“ und die Referenztypen „call by sharing“ übergeben werden.

Ein weiterer Aspekt von „call by reference“ ist, dass man dort etwas übergeben muss, dem man etwas zuweisen kann. Also ``do_something(4711)`` wäre *nicht* möglich — ist es in Python aber selbstverständlich. Bei Pascal und C++ geht das nicht, da kommt eine entsprechende Fehlermeldung vom Compiler. QBasic trickst an der Stelle etwas: Bei Ausdrücken wird eine temporäre anonyme Variable erstellt, die dann per „call by reference“ übergeben wird.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@__blackjack__: Ich sehe da keinen Widerspruch zu deiner Ausführung. In Python ist alles ein Objekt (auch Ausdrücke) und die Argumentübergabe erfolgt mittels Referenzen (wer das kennt, kann damit schon mal was anfangen). Das weitere Verhalten ist vom Typ des Objektes abhängig – eben das, was ich schrieb.
Benutzeravatar
__blackjack__
User
Beiträge: 13119
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kbr: Der Widerspruch ist, dass sich das einfach nicht wie „call by reference“ verhält. Ich habe da oben zwei Beispiele in Pascal und QBasic für „call by reference“ die *den* wichtigen Aspekt zeigen. Das *muss* so funktionieren um von „call by reference“ sprechen zu können. Wenn man so eine Funktion nicht schreiben kann, dann ist es auch kein „call by reference“. Es reicht dafür nicht das Änderungen an einem Objekt ausserhalb sichtbar sind, sondern man muss dem *Namen* etwas zuweisen können, und *das* muss ausserhalb sichtbar sein. Ein anderes Beispiel wäre eine `swap()`-Funktion:

Code: Alles auswählen

def swap(a, b):
    ... # Vertausche `a` und `b`.

def main():
    a = 42
    b = 23
    swap(a, b)
    print(a, b) # Hier müssten jetzt die Werte von `a` und `b` vertauscht sein.
Wenn man jemandem erzählt in Python sei die Übergabe „call by reference“, und der in irgendeinem Lehrbuch zu Compilerbau, oder konkreten Programmiersprachen die *tatsächlich* „call by reference“ machen (können) nachliest, oder gar schon Erfahrung in einer dieser Sprachen wie Pascal, verschiedene BASIC-Dialekte, oder C++ hat, dann wird der sehr überrascht sein, dass sich Python *nicht* wie „call by reference“ verhält. Insbesondere wenn sowieso schon das eigentliche Problem ist, dass Unklarheit besteht was eine Funktion oder Methode aus Sicht eines Aufrufers verändern kann und was nicht, ist es wenig hilfreich zu sagen es wäre „call by reference“, verhält sich aber anders als in allen anderen Sprachen und Lehrbüchern, oh, und was Wikipedia als den „Litmus-Test“ für „call by reference“ bezeichnet (die `swap()`-Funktion) geht auch nicht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@__blackjack__: Meinem Eindruck nach konzentrierst Du Dich zu sehr auf die Definition von "call by reference" an sich, und weniger auf den erklärenden Ansatz, der zu dem Verständnis, wie Python Argumente übergibt, hinführen soll. Dies geht eben über Referenzen. Wer das bereits kennt, kann hier ansetzen. Und dann geht es eben in die Feinheiten, wie Referenz-Kopien, Namespaces, Eigenschaften der referenzierten Objekte ... . Menschen lernen unterschiedlich – insofern kann es sinnvoll sein, sie unterschiedlich abzuholen. Irgendwann steht dann auch das korrekte Verständnis. Mit diesem lässt sich für mutable Objekte gleichen Typs auch 'swap()' aus Deinem Beispiel implementieren (und erklären warum dies geht, aber anders einfacher ginge).
Benutzeravatar
__blackjack__
User
Beiträge: 13119
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kbr: Das hat nichts mit mutable vs. immutable zu tun, denn bei „call by reference“ ist es *egal*, denn das muss mit *jedem* Wert funktionieren. Und letztlich geht das auch mit Listen nicht. Man kann den *Inhalt* der Listen tauschen, aber nicht die Listen *selbst* und *das* müsste gehen wenn es „call by reference“ wäre. Nicht nur der Inhalt wäre dann vertauscht, sondern auch was ``id(a)`` und ``id(b)`` liefern, müsste vertauscht sein. Bei einem erklärenden Ansatz darf man „call by reference“ nicht verwenden, ausser *deutlich* darauf hinzuweisen, das Python *kein* „call by reference“ macht oder gar machen könnte. Denn jeder der weis was „call by reference“ ist, wäre davon extrem verwirrt. Was besonders blöd ist wenn eh schon Verwirrung besteht. Und noch schlimmer wenn die Leute schon Erfahrung mit Sprachen haben die „call by reference“ bieten, gesagt bekommen das wäre in Python auch so, dann aber feststellen das das man damit gar nicht genau das machen kann wofür man „call by reference“ in den schon bekannten Sprachen verwendet.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
grubenfox
User
Beiträge: 432
Registriert: Freitag 2. Dezember 2022, 15:49

__blackjack__ hat geschrieben: Sonntag 18. Dezember 2022, 13:20 ... sondern man muss dem *Namen* etwas zuweisen können, ...
Könnte/sollte man hier auf das "zuweisen" eingehen, welches sich bei Python von anderen Sprachen (Pascal, Basic, usw.) unterscheidet?
Benutzeravatar
__blackjack__
User
Beiträge: 13119
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@grubenfox: Ja natürlich, gerade *weil* sich das unterscheidet ist das ja genau dann besonders wichtig wenn es um Verständnisprobleme geht, von Leuten die von anderen Sprachen ein anderes Verhalten gewohnt sind. Und natürlich auch weil das zentral in der Definition von „call by reference“ ist. Eine Zuweisung an den Argumentnamen muss sich so verhalten als wenn man diese Zuweisung im Kontext des Aufrufers gemacht hätte. Das ist die Definition von „call by reference“ oder ergibt sich zumindest zwingend daraus wenn es anders formuliert ist. Und auch aus den Beispielen, die man für „call by reference“ kennt. Wenn das „call by reference“ wäre, würde es ja auch gar keinen Grund geben etwas „call by sharing“ zu nennen wenn das das gleiche wäre.

C++ geht sogar noch weiter, da kann man Referenzen auch als Rückgabewert haben und so etwas wie ``do_something() = 42``, was in Python grundsätzlich ein Syntaxfehler ist, würden C++-Programmierer erwarten wenn man einfach sagt, dass in Python alles Referenzen sind.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13119
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Holzbein: Vielleicht noch mal zurück zum Beispiel:

Das `copy`-Modul wird nirgends verwendet, man kann das als Beispiel auch in ein Modul stecken.

Die beiden Methoden machen letztlich ja das gleiche, nur mit einem anderen Schlüssel, den könnte man also *einer* Methode als Argument mitgeben.

Zusammengefasst und gekürzt, ohne tatsächlich etwas zu ändern, wäre das hier der Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict


class Sensors:
    def __init__(self, config_data):
        self.data = config_data["Sensors"]

    def do_something(self, key):
        return defaultdict(dict, {key: self.data[key] * 2})


def main():
    sensors_data = defaultdict(
        dict, {"Sensors": defaultdict(dict, {"actualVal": 3, "maxVal": 10})}
    )

    sensors = Sensors(sensors_data)
    print("original sensors_data:")
    print(sensors_data)
    print()

    # return "maxVal" should change to 20
    result = sensors.do_something("maxVal")
    print("1. result :")
    print(result)  # OK
    print()

    sensors_data["Sensors"]["maxVal"] = 20  # "maxVal" set to 20
    result = sensors.do_something("maxVal")  # return "maxVal" should =40
    print("2. result :")
    print(result)  # OK
    sensors_data["Sensors"] = result  # "maxVal" set to (returned) 40
    print("2. sensors_data:")
    print(sensors_data["Sensors"])  # 40 !!!  it seems to be updated!!!
    print()

    result = sensors.do_something("maxVal")  # return "maxVal" should =80
    print("3. result:")
    print(result)  # NO !!
    print()

    sensors_data["Sensors"]["Val"] = 90
    result = sensors.do_something("Val")
    print("4. result:")
    print(result)
    print()


if __name__ == "__main__":
    main()
Zwei Sachen fehlen im Text zum ersten Beitrag. Das eine ist Dir vielleicht nicht aufgefallen, unter anderem vielleicht auch wegen dem ”Rauschen” das `defaultdict` in der Ausgabe erzeugt: Bei der Ausgabe von "2. sensors_data:" fehlt ganz offensichtlich "actualVal" in der Datenstruktur, was so sicher nicht gewollt war. Du ersetzt die gesamte Datenstruktur mit dem Rückgabewert, der aber nur *eins* von den beiden Schlüssel-/Wert-Paaren enthält.

Was ich dagegen nicht nachvollziehen kann ist das Du nichts darüber geschrieben hast, dass man zur Ausgabe von 4. gar nicht kommt, weil das vorher mit einer Ausnahme abbricht:

Code: Alles auswählen

original sensors_data:
defaultdict(<class 'dict'>, {'Sensors': defaultdict(<class 'dict'>, {'actualVal': 3, 'maxVal': 10})})

1. result :
defaultdict(<class 'dict'>, {'maxVal': 20})

2. result :
defaultdict(<class 'dict'>, {'maxVal': 40})
2. sensors_data:
defaultdict(<class 'dict'>, {'maxVal': 40})

3. result:
defaultdict(<class 'dict'>, {'maxVal': 40})

Traceback (most recent call last):
  File "forum21.py", line 77, in <module>
    main()
  File "forum21.py", line 70, in main
    result = sensors.do_something("Val")
  File "forum21.py", line 36, in do_something
    return defaultdict(dict, {key: self.data[key] * 2})
TypeError: unsupported operand type(s) for *: 'dict' and 'int'
Diese verschachtelten ``defaultdict(dict)`` sind wirklich keine gute Idee. Und wirklich verwendet wird das ja auch gar nicht, die einzige Stelle wo auf einen nicht-existierenden Schlüssel zugegriffen wird, liefert das ganz offensichtlich einen ungeigneten Wert für die Operation die damit durchgeführt werden soll. Eine Ausnahme kann man da auch mit normalen Wörterbüchern bekommen, ohne das an allen anderen Stellen unnötig kompliziert zu machen:

Code: Alles auswählen

#!/usr/bin/env python3


class Sensors:
    def __init__(self, data):
        self.data = data

    def do_something(self, key):
        return {key: self.data[key] * 2}


def main():
    sensors_data = {"Sensors": {"actualVal": 3, "maxVal": 10}}

    sensors = Sensors(sensors_data["Sensors"])
    print("original sensors_data:")
    print(sensors_data)
    print()

    # return "maxVal" should change to 20
    result = sensors.do_something("maxVal")
    print("1. result :")
    print(result)  # OK
    print()

    sensors_data["Sensors"]["maxVal"] = 20  # "maxVal" set to 20
    result = sensors.do_something("maxVal")  # return "maxVal" should =40
    print("2. result :")
    print(result)  # OK
    sensors_data["Sensors"] = result  # "maxVal" set to (returned) 40
    print("2. sensors_data:")
    print(sensors_data["Sensors"])  # 40 !!!  it seems to be updated!!!
    print()

    result = sensors.do_something("maxVal")  # return "maxVal" should =80
    print("3. result:")
    print(result)  # NO !!
    print()

    sensors_data["Sensors"]["Val"] = 90
    result = sensors.do_something("Val")
    print("4. result:")
    print(result)
    print()


if __name__ == "__main__":
    main()
Eine Funktion/Methode die ein Wörterbuch mit genau einem Schlüssel-/Wert-Paar erstellt ist auch ein „code smell“. Das kann unter Umständen Sinn machen, aber das ist eher selten.

Bei 3. wird nicht 80 ausgegeben weil die Klasse immer noch das Wörterbuch hat das ursprünglich mal ``sensors_data["Sensors"]`` war, das Du aber im Schritt davor durch ein anderes Wörterbuch ersetzt hast. Dieses komplette ersetzen ist ja auch der Grund warum dort "actualVal" verschwunden ist. Das war also sowieso falsch.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@__blackjack__: Es ging mir darum, jemanden, der bereits "call by reference" kennt, dort nicht stehenzulassen, sondern abzuholen. Dieser "Abholungspunkt" entspricht nicht dem, was du als "call by (object) sharing" bezeichnest, und ist in meinem früheren Post sicher etwas unglücklich ausgedrückt. Durch das Abholen von "call by reference" wird allerdings auch klar, dass es eben Unterschiede gibt. Insofern sind deine Arguments das es sich nicht um "call by reference" handelt alle richtig, aber lassen vermuten, genau dies sei behauptet worden. Das ist nicht der Fall.
Antworten