Seite 1 von 1

Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 15:16
von Mate
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)

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 15:57
von BlackJack
@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.

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 16:47
von mutetella
@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:

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 17:13
von Mate
@ 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

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 18:56
von Sirius3
@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

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 19:13
von Mate
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]

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 19:26
von Mate
@sirius3 Danke, ich werde mir itertools mit zip_longest bei meiner nächsten Pythonsession mal genauer anschauen.

Die ToDo Liste wird größer

Re: Erste Programme, Verbesserungsvorschläge

Verfasst: Dienstag 24. November 2015, 19:31
von Mate
@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