Code verstehen

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.
Antworten
RcReese
User
Beiträge: 8
Registriert: Donnerstag 21. November 2019, 18:15

Hallo,
Ich sitze vor einem Code der nicht von mir geschrieben wurde und habe Probleme zu verstehen was genau da passiert....

Die Code-Zeilen lauten:

Code: Alles auswählen

gencode_building_all = list(itertools.product([0,1], repeat=8))
pop_building = []
for i, pop in enumerate(gencode_building_all):
    stringliste = ""
    for j in pop:
        stringliste = stringliste + str(j)
        pop_building.append(stringliste)
Die Liste gencode_building_all besteht ja aus 256 Einträgen, deshalb verstehe ich nicht wie über die for-Schleife(n) 2048 Einträge in pop_building entstehen?
In gencode_building_all sind ja 256 Einträge die alle jeweils 8 Stellen haben und nur aus 0 und 1 bestehen. In pop_building sind die Einträge von der Länge her zwischen 1 und 8 Stellen variabel. Ich verstehe nur nicht wieso das so ist?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

pop ist ein Element aus gencode_building_all, das wiederum 8 Eintraege 0/1 enthaelt. Und jetzt hast du eine auessere Schleife ueber alle 256 Eintraege, und dann eine innere Schleife ueber alle Element aus eben einem Eintrag pop. Und die sind 8 lang, also hast du 8 * 256 append-Vorgaenge fuer die Liste pop_building.

Wenn ich mir das so ansehe vermute ich mal, was da eingentlich passieren soll ist, dass pop_building.append eine Ebene hoeher soll, um nur den *letzten* Wert von stringliste anzufuegen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein Einzeiler, der sich auch unnoetige Dinge wie das enumerate spart:

Code: Alles auswählen

pop_building = ["".join(str(bit) for bit in pop) for pop in gencode_building_all]
RcReese
User
Beiträge: 8
Registriert: Donnerstag 21. November 2019, 18:15

Alles klar, danke das hilft beim Verständnis ! :)
RcReese
User
Beiträge: 8
Registriert: Donnerstag 21. November 2019, 18:15

Ich möchte nicht nochmal ein neues Thema aufmachen, da es sich hier auch teilweise um ein Verständnisproblem handelt...

Wieder ein Code der nicht von mir ist und wie folgt aussieht:

Code: Alles auswählen

pool = multiprocessing.Pool(12)
results_heat = [pool.map_async(partial(calculation, zoneInputs=zoneInputs), arguments)]
heatload_result=([p.get() for p in results_heat])[0]

Hier soll nun in heatload_result nur die positiven Einträge aus results gespeichert werden und die negativen durch 0 ersetzt werden...
Mit einer einfachen if-Abfrage bekomme ich allerdings die Fehlermeldung:

'>=' not supported between instances of 'MapResult' and 'int'

Daraufhin habe ich versucht das map-object mit

Code: Alles auswählen

results=list(results_heat)
in eine Liste zu überführen, das hat allerdings auch nicht geholfen...
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte die vollstaendige Fehlermeldung zeigen. Nicht nur eine Paraphrasierung.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@RcReese: wenn der Code nicht von Dir ist, warum benutzt Du den dann, da er ja offensichtlich nicht funktioniert und unsinnig ist.
Ein map_async-Objekt in eine einelementige Liste zu packen ist Quatsch. `get` darauf aufzurufen, habe ich noch nie gesehen, ich weiß nichtmal was das zurückgibt.

Code: Alles auswählen

pool = multiprocessing.Pool(12)
heatload_result = list(pool.map_async(partial(calculation, zoneInputs=zoneInputs), arguments))
Ist Multiprocessing hier überhaupt nötig? Wenn nein, dann weg damit, wenn doch, dann solltest Du genau verstehen, was der Code macht und nicht nur irgendetwas von irgendwoher kopieren.
RcReese
User
Beiträge: 8
Registriert: Donnerstag 21. November 2019, 18:15

Die vollständige Fehlermeldung lautet:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_umd.py", line 197, in runfile
pydev_imports.execfile(filename, global_vars, local_vars) # execute the script
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "/Users/heatload_calculation.py", line 54, in <module>
result = heatload.fHeatload(building)
File "/Users/heatload.py", line 217, in fHeatload
if p>=0:
TypeError: '>=' not supported between instances of 'MapResult' and 'int'


@Sirius3: Der Code stammt von einem funktionierenden Tool das ich im Rahmen meiner Masterarbeit an veränderte Bedingungen/Bedürfnisse anpassen soll, deswegen muss ich schon mit dem vorhandenen Code arbeiten und kann leider nicht alles über Bord schmeißen
einfachTobi
User
Beiträge: 512
Registriert: Mittwoch 13. November 2019, 08:38

Deine Ergebnisse stehen in `heatload_result`. Um dir anzuschauen, was du genau zurückbekommst empfehle ich zunächst:

Code: Alles auswählen

heatload_result=[p.get() for p in results_heat]
print(heatload_result)
So kannst du erstmal überprüfen, ob du die erwarteten Werte bekommst oder ob du noch etwas anders sortieren musst. Da ich davon ausgehe, dass es sich um Simulationsergebnisse im weitesten Sinne handelt, mit denen im Anschluss gerechnet werden soll, bietet sich die Verwendung von Numpy an.
Um alle Elemente < 0 zu ersetzen kannst du folgendes machen:

Code: Alles auswählen

heatload_result = np.array(heatload_result)
heatload_result[heatload_result < 0] = 0
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Fehlermeldung bringt genau "nichts", weil der passende Code dazu fehlt.
Meine Motivation zu Helfen sinkt auch rapide, wenn sich der Hilfesuchende nicht wenigstens bemüht, Python zu lernen, sondern nur möglichst kostenlos sich sein Programm so anpassen zu lassen, dass er keine Probleme mehr damit hat.
Wenn Deine Aufgabe ist, Code an Bedürfnisse anzupassen, dann ist es auch Deine Aufgabe Python so weit zu lernen, dass Du das selbständig tun kannst.
Anpassen heißt im ersten Schritt fast immer, den Code so zu verändern, dass er sinnvoll und verständlich ist.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@RcReese: Du musst dann aber schon Code zeigen der tatsächlich so ausgeführt wird, denn der hier steht da ganz sicher nicht so:

Code: Alles auswählen

pool = multiprocessing.Pool(12)
results_heat = [pool.map_async(partial(calculation, zoneInputs=zoneInputs), arguments)]
heatload_result=([p.get() for p in results_heat])[0]
Denn das wäre extrem unsinnig, aus den von Sirius3 genannten Gründen. Man steckt auch nicht *ein* Element in eine Liste und man benutzt dann auch keine „list comprehension“ um aus einer Liste mit immer genau *einem* Element, eine weitere Liste mit immer genau *einem* Element zu machen und aus der dann das eine Element per Indexzugriff zu holen.

Wenn man diese völlig absurden einelementigen Listen weg lässt, bleibt das hier übrig:

Code: Alles auswählen

    heatload_result = (
        multiprocessing.Pool(12)
        .map_async(partial(calculation, zone_inputs=zone_inputs), arguments)
        .get()
    )
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Nachtrag: Sofort nach `Pool.map_async()` die `get()`-Methode auf dem Ergebnis aufrufen ist natürlich auch unsinnig, denn das ist als Kombination genau das was die `Pool.map()`-Methode bereits macht:

Code: Alles auswählen

    heatload_result = multiprocessing.Pool(12).map(
        partial(calculation, zone_inputs=zone_inputs), arguments
    )
Das sieht doch wesentlich kürzer und verständlicher aus als das Original. Vor Dir scheint das also auch jemand gemacht zu haben der wenig Ahnung von Python hat, beziehungsweise generell vom Programmieren.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
RcReese
User
Beiträge: 8
Registriert: Donnerstag 21. November 2019, 18:15

@einfachTobi: Danke für deine Hilfe, mit diesem Ansatz kann ich weiterarbeiten.

@__blackjack__: Es ist tatsächlich nicht der gesamte Code, aber doch diese 3 Zeilen stehen tatsächlich genau so da. Vielen Dank fürs Aufzeigen wie das sinnvoller in Python geschrieben werden kann. Das sieht tatsächlich schon übersichtlicher aus und wohl auch leichter zu verstehen.

@Sirius3: Ich bin genau dabei zu versuchen Python so weit zu erlernen dass ich meine Masterarbeit damit schreiben kann, deswegen ist es ja wichtig den geschriebenen Code zu verstehen, womit ich viel Zeit verbringe. Wenn ich nach mehreren eigenen Versuchen nicht weiter komme wende ich mich hier an das Forum um Hilfe zu erhalten, ich denke deswegen gibt es solche Foren oder? Und nein, da ich nur begrenzt Zeit habe für meine Arbeit und das Tool aus mehreren Tausend Zeilen Code besteht, habe ich keine Zeit das alles erst so umzuschreiben dass es deinem Verständnis von sinnvoll entspricht. Es mag ja sein, dass einiges davon für einen Python-Kenner unlogisch erscheint, das kann ich allerdings nicht auf den ersten Blick beurteilen und daran habe ich auch keinen Anteil. Trotzdem Danke für deine Mühe.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@RcReese: Das Problem ist IMHO nicht das der gezeigte Code vom Python-Kenner nicht so geschrieben werden würde, sondern das mit den einelementigen Listen und unnötigen Klammern sieht halt danach aus als wenn der Autor davon generell nicht wirklich programmieren kann/konnte.

Anstelle von dem hier:

Code: Alles auswählen

    pool = multiprocessing.Pool(12)
    results_heat = [pool.map_async(partial(calculation, zoneInputs=zoneInputs), arguments)]
    heatload_result=([p.get() for p in results_heat])[0]
hätte da wirklich das hier stehen müssen:

Code: Alles auswählen

    pool = multiprocessing.Pool(12)
    result_heat = pool.map_async(partial(calculation, zoneInputs=zoneInputs), arguments)
    heatload_result = result_heat.get()
denn der Unterschied zwischen den beiden ist, dass der erste Schnippsel Code enthält der *nichts* macht, ausser den Code unnötig zu verkomplizieren. Ich weiss gar nicht wie man auf die Idee kommen kann das in unnötige einelementige Listen zu stecken.

Umschreiben solltest Du es nicht nur für uns, sondern auch für Dich, denn Code der nur dazu da ist, dass es schwerer verständlich ist, macht nur Probleme. Jetzt Dir, später dem nächsten der mit der Code-Basis etwas machen muss.

Falls Du es nicht umschreiben kannst, weil Du es nicht verstehst, dann kannst Du den Code natürlich hier zeigen. Du solltest dann aber a) verstehen warum der umgeschriebene, einfachere Code dem unnötig komplizierten Code entspricht, und b) die Änderungen mindestens in solchen krassen Fällen auch in das Programm übernehmen. Wie gesagt, der nächste wird sich freuen. Wobei der nächste auch der originale Autor oder Du selbst sein kannst. Denn wenn man lange genug nicht in den eigenen Code oder Code den man mal verstanden hat, rein schaut, muss man sich wieder einarbeiten.

Das mit dem verstehen des umgeschriebenen Codes und wie der mit dem Original in Beziehung steht, ist vielleicht auch wichtig für den restlichen Originalcode, falls da weitere Abwege in der Art enthalten sind.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten