Erste Programme, Verbesserungsvorschläge

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
Mate
User
Beiträge: 7
Registriert: Sonntag 15. November 2015, 19:36

Dienstag 24. November 2015, 15:16

Hallo an alle,

ich lerne nun seit fast zwei Monaten Python aus Büchern und durch Internetseiten. Mein Ziel ist es auf lange Sicht einen schönen nachvollziehbaren und logischen Code zu schreiben. Dafür würde ich mich freuen, wenn sich jemand findet der sich meine Prozedur anschaut und mir Tipps zur besseren
Gestaltung
Verwendung von Funktionen, Methoden, Module

anhand der Beispiele geben würde die ich poste.
Bei der Matrizenberechnung bin ich natürlich auch an möglichen Modulen oder Funktionen interessiert, die den ganzen Prozess vereinfachen. Im Vordergrund stand hier jedoch für mich der richtige Gebrauch von Listen, einer Schleife und der Gestaltung eigener Funktionen.

Code: Alles auswählen

def Matrizen(m1,m2):
    """Prüft, ob Matrizen-Multiplikation möglich ist.
    Wenn möglich, erfolgt Matrizen-Multiplikation"""
    if len(m1[0]) == len(m2):
        Liste = []
        for row in range(0, len(Matrix1)):
            for item in range(0,len(Matrix1[0])):
                Wert = 0
                for vertikal in range(0,len(Matrix1[0])):
                    Wert += (Matrix1[row][vertikal] * Matrix2[vertikal][item])
                Liste.append(Wert)
    else:
        print("Matrizen-Multiplikation nicht möglich")
    return Liste

def convert_list_to_matrix(list, row_items = 0):
    if row_items >= 0:
        for slicing in range(0, (len(list)/row_items)):
            pass   # Anregungen??
        
Matrix1 = [[2,1,0],
           [3,-1,1],
           [2,1,1]]
Matrix2 = [[7,1,5],
           [4,-1,7],
           [2,1,0]]

Liste = Matrizen(Matrix1, Matrix2)
print(Liste)
Zuletzt geändert von Anonymous am Dienstag 24. November 2015, 15:48, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

Dienstag 24. November 2015, 15:57

@Mate: Die Namensschreibweisen halten sich nicht alle an den Style Guide for Python Code.

Funktionen und Methoden werden üblicherweise nach Tätigkeiten benannt damit man weiss was die *tun*. Das wird aus dem Namen `Matrizen` überhaupt nicht ersichtlich.

Was passiert wenn die Multiplikation nicht möglich ist, hast Du anscheinend nicht ausprobiert. Statt *der* Ausnahme sollte anstelle des `print()` eine *passende* Ausnahme ausgelöst werden.

Braucht man für die Multiplikation wirklich *drei* verschachtelte Schleifen‽

Die Namen `row`, `vertikal`, und `item`, passen als Indexnamen auch nicht wirklich zusammen. Neben der Deutsch/Englisch-Mischung wäre das eher `row` und `column` oder `horizontal` und `vertikal`. `item` ist kein Name für einen Index sondern für ein Element.

Anstelle einer flachen Liste hätte ich eine Matrize als Ergebnis erwartet.

An Modulen/Packages fällt einem hier natürlich als erstes Numpy ein, dann braucht man sich so eine Multiplikation nicht selber programmieren.
mutetella
User
Beiträge: 1690
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Dienstag 24. November 2015, 16:47

@Mate
Die Namen (im Namensraum des Moduls) `Matrix1` und `Matrix2` zeigen jeweils auf eine Liste. Nun übergibst Du via diesen beiden Namen die beiden Listen an Deine Funktion und bindest dort die Namen (im Namensraum der Funktion) `m1` und `m2` an dieselben beiden Listen. Weshalb verwendest Du dann innerhalb der Funktion einmal die Funktions- und dann wieder die Modulnamen? Zum einen kann das verwirrend sein, zum anderen sollten globale Namen (und das sind erst einmal die Namen, die auf Modulebene vergeben werden) eigentlich nicht verwendet werden. In umfangreicheren Anwendungen verliert man damit sehr schnell den Überblick oder findet Fehler sehr sehr schwer, weil man irgendwann nicht mehr erkennt, wo und wer alles via diesen Namen Werte verändert.

Ein weiteres potentielles Problem beim Verweis mehrerer Namen auf dieselbe Liste/dasselbe Dictionary über verschiedene Namensräume hinaus:

Code: Alles auswählen

>>> def change_within_function_scope(any_list):
...     any_list.append('appended within function')
... 
>>> any_list_from_outside = []
>>> any_list_from_outside.append('appended outside')
>>> any_list_from_outside
['appended outside']
>>> change_within_function_scope(any_list_from_outside)
>>> any_list_from_outside
['appended outside', 'appended within function']
Das ist auch mit ein Grund, weshalb es fast immer eine gute Idee ist, eine bestehende Liste/ein bestehendes Dictionary nicht inplace zu ändern, sondern über die Werte zu gehen und aus den veränderten Werten dann eine neue Liste/ein neues Dictionary zu erstellen.

In Deinem Beispiel macht dieses Verhalten kein Problem, aber Du solltest es im Hinterkopf behalten... erspart Dir späteren Wahnsinn... :mrgreen:
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Mate
User
Beiträge: 7
Registriert: Sonntag 15. November 2015, 19:36

Dienstag 24. November 2015, 17:13

@ Blackjack
Werde ein mir den Styleguide genauer anschauen. Nach soetwas habe ich gesucht.

Ja den Fall "Multiplikation nicht möglich" habe ich tatsächlich nicht ausprobiert, da war der Hunger zu groß und ich wollte den Code noch schnell posten.

Mit meinem derzeitigen Wissen sah ich leider keine andere Möglichkeit. Es ging mir übrigens bei diesem Post genau um diesen drei Schleifen-Abschnitt. Wäre an anderen Wegen sehr interessiert.

Super, Numpy. Habe ich bereits runtergeladen und in Python integriert. Jedoch noch keine Zeit gehabt mich damit näher zu beschäftigen. Ich wollte mich zuerst auf die Basics konzentrieren. Dann setze ich Numpy auf meine Prioritätenliste.

@mutella
Das die "Matrix1" in der Funktion steht ist mir tatsächlich nicht aufgefallen. Hatte den Code für Schnelltests außerhalb der Funktion geschrieben und diesen Teil anschließend schnell in die Schleife kopiert... Ein schönes Beispiel für Seiteneffekte. Nun habe ich das auch mal in einem Programmablauf gesehen.

Cool danke euch beiden, dass ihr euch die Zeit genommen habt
Sirius3
User
Beiträge: 8805
Registriert: Sonntag 21. Oktober 2012, 17:20

Dienstag 24. November 2015, 18:56

@Mate: besser ist es, statt über einen Index zu iterieren, direkt über die Listen.

Code: Alles auswählen

from itertools import zip_longest

def multiply_matrix(m1, m2):
    m2t = list(zip_longest(*m2))
    result = []
    for row_m1 in m1:
        result_row = []
        for column_m2 in m2t:
            result_row.append(sum(a * b for a, b in zip_longest(row_m1, column_m2)))
        result.append(result_row)
    return result
Mate
User
Beiträge: 7
Registriert: Sonntag 15. November 2015, 19:36

Dienstag 24. November 2015, 19:13

Ok hier meine überarbeitete Version, in der ich versucht habe vieles anzuwenden, was ich bisher gelernt habe.
@ BlackJack ich habe ein paar Stilfehler durch den Style Guide in meinem Code zu gefunden. Sind noch mehr vorhanden?

Ich habe immer noch keine Idee wie ich
- eine bessere Variante der drei Schleifen der Funktion "matrizen_multiplikation" schreibe.
- die flache Liste in eine Matrix konvertiere ohne Numpy zu nutzen.

[codebox=python file=Unbenannt.txt]def matrizen_multiplikation(m1,m2):
"""Multipliziert zwei Matrizen miteinander"""
liste = []
for row in range(0, len(m1)):
for index in range(0,len(m1[0])):
value = 0
for column in range(0,len(m1[0])):
# bei m1 entpricht column dem index
value += (m1[row][column] * m2[column][index])
liste.append(value)
print(liste)
return liste

def convert_list_to_matrix(list, row_index=0):
"""Unfertige Funktion: Soll flache Liste in Matrix umwandeln"""
if row_index >= 0:
for slicing in range(0, (len(list)/row_index)):
pass # Anregungen??

matrix1 = [[2,1,0],
[3,-1,1],
[2,1,1]]
matrix2 = [[7,1,5],
[4,-1,7],
[2,1,0]]

try:
liste1 = matrizen_multiplikation(matrix1, matrix2)
except UnboundLocalError as err1:
print("Matrizen-Multiplikation nicht möglich.\n{}".format(err))
except IndexError as err2:
print("Matrizen eignen sich nicht zur Multiplikation.\n{}".format(err2))
except TypeError as err3:
print("Zweites Argument nicht vorhanden.\n{}".format(err3))[/code]
Mate
User
Beiträge: 7
Registriert: Sonntag 15. November 2015, 19:36

Dienstag 24. November 2015, 19:26

@sirius3 Danke, ich werde mir itertools mit zip_longest bei meiner nächsten Pythonsession mal genauer anschauen.

Die ToDo Liste wird größer
Mate
User
Beiträge: 7
Registriert: Sonntag 15. November 2015, 19:36

Dienstag 24. November 2015, 19:31

@sirius3 ich hatte anfangs über die Listen selber iteriert, jedoch gab es Seiteneffekte.
Beispiel [2,1,1]. Die beiden 1er waren ein Objekt. Wenn iteriert wurde sahen die Indexe deshalb so aus
0 1 1 statt
0 1 2
Antworten