Magic Methods

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Gelöscht2200

Hallo ich soll ein Programm schreiben, in dem u.a. die Addition und Subtraktion zweier Vektoren als magic method implementiert werden soll. Soweit mein Programm

Code: Alles auswählen

from __future__ import division
from sympy import *

import numpy as np	
import csv



readVektor = csv.DictReader(open("data.csv"))           # Einlesen der CVS-Datei

for column in readVektor:       # Ausgeben der CSV-Datei-INhalte
        print (column)
        
for column in readVektor:       # Parsen der Inhalte der CSV-Datei
        id = int(column["id"])
        length = int(column["lenght"])

        index = [int(x) for x in column["index"].split(' ')]
        value = [int(x) for x in column["value"].split(' ')]



class sparse(object):		# Klasse, deren Objekte sparse Vektoren sind
	
			
        def __init__(self, index, value, lenght):       # Konstruktor
                self.Index = index  
                self.Value = value 
                self.Laenge = lenght    

        
        def maxNorm(self, value):		# Berechnung der Maxmimums-Norm
                maxNorm = max(value)
                max_idx = value.index(maxNorm)
                #return max_idx, maxNorm
                print ("maxNorm: ", maxNorm)
			

        def sMult(self, value1, value2):		# Skalarmultiplikation
                sMult = value1 * value2
                #return sMult
                print ("sMult: ", sMult)

	
        def Summe(self, index1, index2, value1, value2): 	# Berechnung der Summe
                #for i, j in range(len(index1, index2)):
                #        if index1(i) < index2(i):
                #                self.summe(i) = value1(i)
                #        if index1(i) > index2(i):
                #                self.summe(i) = value2(i)
                #        if index1(i) == index2(i):
                #                self.summe(i) = value1(i) + value2(i)
                #        return summe
                summe = value1 + value2
                #return summe
                print ("summe: ", summe)


        def Differenz(self, index1, index2, value1, value2):
                differenz = value1 - value2
                #return differenz
                print ("differenz: ", differenz)


        def __add__(self, other):
        
        
        
        def __sub__(self,other):
        

		
        def iProd(self, value1, value2):
                iProd = np.dot (value1, value2)
                #return iProd
                print ("iProd: ", iProd)


        #def Differenz(self, index1, index2, value1, value2):				# Berechnung der Differenz
	#	for i in range(len(index1, index2))
	#		if index1(i) < index2(i)
	#			self.differenz(i) = value1(i)
	#		if index1(i) > index2(i)
	#			self.differenz(i) = value2(i)
	#		if index1(i) == index2(i)
	#			self.differenz(i) = value1(i) - value1(i)
		
		#self.differenz = value1 - value2
		


        
	#def Skalarprodukt(self, value1, value2):			#Skalarprodukt
	#	for i in range(len(index1, index2))
	#		if index1(i) < index2(i)
	#			self.skalarprodukt(i) = 0
	#		if index1(i) > index2(i)
	#			self.skalarprodukt(i) = 0
	#		if index1(i) == index2(i)
	#			self.skalarprodukt(i) = value1(i) * value1(i)
		
		#self.skalarprodukt = np.dot(value1, value2)		
		 
#print ("maxNorm: ", maxNorm)
#print ("summe: ", summe)
#print ("differenz: ", differenz)
#print ("sMult: ", sMult)
#print ("iProd: ", iProd)

sparsevector1 = sparse([2,9,5],[2,9,5],10)
sparsevector2 = sparse([3,5,8],[3,5,8],10)
sparsevector3 = sparse([1],[7],1)

sparsevector1.maxNorm([2,9,5])
sparsevector2.maxNorm([3,5,8])

sparsevector1.sMult(7,[2,9,5])
sparsevector2.sMult(7,[3,5,8])

sparsevector1.Summe([2,9,5],[3,5,8],[2,9,5],[3,5,8])
sparsevector2.Summe([2,9,5],[3,5,8],[2,9,5],[3,5,8])

#sparsevector1.Differenz([2,9,5],[3,5,8],[2,9,5],[3,5,8])
#sparsevector2.Differenz([2,9,5],[3,5,8],[2,9,5],[3,5,8])

sparsevector1.iProd([2,9,5],[3,5,8])
sparsevector2.iProd([2,9,5],[3,5,8])

Die magic methods beginnen mit

Code: Alles auswählen

def __sub__(self,other):
bzw.

Code: Alles auswählen

def __add__(self,other):
Wie fülle ich diese functionen aus und wie rufe ich die Methoden auf?
Zuletzt geändert von Gelöscht2200 am Mittwoch 18. November 2015, 21:43, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@loyloep: so funktioniert Programmieren nicht. Du brauchst dringend mehr Struktur. Am besten löschst Du alles und fängst von vorne an. Was ist gegeben, was ist das Ziel? Welche Schritte sind nötig um das Ziel zu erreichen?
Gelöscht2200

Die Struktur ist mir momentan weniger wichtig. Da ich das Programm bis Freitag fertig haben muss.

Ich möchte verstehen wie ich mittels der magic methods zwei Vektoren addieren und subtrahieren kann. :K
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

In der Python Dokumentation gibt es, vielleicht etwas versteckt, eine Seite zum Data Model. Wenn du ein Lesezeichen zu irgendeiner Seite in der Dokumentation haben solltest dann dieser. Dort findet sich auch alles was du wissen musst.

Sowas kann man allerdings auch sehr gut ausprobieren:

Code: Alles auswählen

class TestObject(object):
    def __init__(self, name):
        self.name = name

    def __add__(self, other):
        print '{} + {}'.format(self.name, other.name)
        return 'foo'

    def __sub__(self, other):
        print '{} - {}'.format(self.name, other.name)
        return 'bar'

Code: Alles auswählen

λ python -i foo.py 
>>> TestObject('a') + TestObject('b')
a + b
'foo'
>>> TestObject('a') - TestObject('b')
a - b
'bar'
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@loyloep: das mag jetzt für Dich hart klingen. Keine einzige Zeile, bis vielleicht die erste, ergibt für mich einen Sinn. Dein Wissensstand ist nach meiner Einschätzung Wochen hinter dem, was für Deine Aufgaben notwendigen ist. Wenn Du so weiter machst, kannst Du gleich hinschmeißen. Ich hoffe, Du wachst bald auf, und setzt Dich wirklich hin und fängst von vorne an. Ohne fundierte Grundlagen kommst Du nicht weiter. Daher nochmal die Frage: Was ist die Aufgabe? Was ist gegeben? Welche Schritte denkst Du, brauchst Du?
Gelöscht2200

Ich habe das jetzt so programmiert:

Code: Alles auswählen

def __add__(self,other):
                return tuple( (a+b for a,b in zip(self.value, other.value) ) )

def __sub__(self,other):
                return tuple( (a-b for a,b in zip(self.value, other.value) ) )
Allerdings wird nichts ausgegeben. Woran liegt das?
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das sieht zwar schon zu 3/4 gut aus, aber was fuer eine Ausgabe erwartest du? Der Code macht keine so wie du ihn da zeigst.

Und denk mal darueber nach, welchen Typ das Ergebnis deiner Operationen hat, und ob dir da nicht noch eine Kleinigkeit fehlt...
Gelöscht2200

Ich habe natürlich das "print" vergessen: Mit diesem Code wird aber auch nichts ausgegeben???

Code: Alles auswählen


        def __add__(self,other):
                return tuple( (a+b for a,b in zip(self.value, other.value) ) )
                print ("add: ", a+b)
                

        def __sub__(self,other):
                return tuple( (a-b for a,b in zip(self.value, other.value) ) )
                print ("sub: ", a-b)

@__deets__: Dein Hinweis nach dem Typ des Ergebnis der Operation muss ich nach einigen forschen so beantworten: Scheinbar ist es keine "list" sondern ein "tuple". Mir fällt jedoch nicht auf welche Kleinigkeit da fehlt???
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Nach einem return wird jede Funktion, bzw. hier Methode verlassen, der Code danach wird ignoriert.

Auch sollte in den Variablen a, b nicht all die Information sein, die du dir erwünscht. Es sind ja "nur" Zähler variablen in einer Schleife.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Tuple oder Liste ist nicht worum es geht. Wird auf dem Rueckgabewert deine Special-Method wieder funktionieren, um zB a+b+c zu rechnen?
Gelöscht2200

@Sr4l: Danke für die Info!

@__deets__: Wenn D uschon so fragts, ob der Rückgabewert wieder funktionieren wird um damit weiterzurechnen. Vermute ich das nicht. Oder? Das ist aber auch nicht zu schlimm. Du kannst mir natürlich gerne verraten, wie man dem mit einer Kleinigkeit Abhilfe schaffen kann.

Ansonsten suche ich erstmal einen Weg, das Ergebnis der beiden Methoden auszugeben. Ersetze ich

Code: Alles auswählen

return
durch

Code: Alles auswählen

print
erhalte ich eine Fehlermeldung: "invalid syntax".
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@loyloep: Ich gebe Dir anbei ein Beispiel für eine Vector-Klasse. Auf dieser sind anschließend Operationen wie a + b und c + d möglich (Frage: warum ist das so?):

Code: Alles auswählen

class Vector:

    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
        
a = Vector(2, 3)
b = Vector(4, 2)
c = a + b
d = a + c
Bei Dir gibt es zudem irgendwas mit "sparse"-Vektor. Was immer das auch sei, da werden bestimmt Vorgaben zu gehören.
Gelöscht2200

Ich habe es nun so programmiert, aber es wird noch immer nichts ausgegeben??

Code: Alles auswählen


def __add__(self,other):
                add = tuple( (a+b for a,b in zip(self.value, other.value) ) )
                print ("add: ", add)
                

def __sub__(self,other):
                sub =  tuple( (a-b for a,b in zip(self.value, other.value) ) )
                print ("sub: ", sub)
                
                
                
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@loyloep: so macht die Methode aus mehreren Gründen keinen Sinn. Sie braucht einen Rückgabewert, der am besten dem entspricht, was der Nutzer erwartet und kein print. add ist auch ein sehr schlechter Name für das Ergebnis einer Addition. Zeig doch, was Du insgesamt hast, aber bitte ohne den ganzen Müll, den Du immer dabei hast, aber nicht brauchst.
Gelöscht2200

Mit welchen Befehlen ausser print lassen sich sich denn noch die Werte der Methode __add__ und __sub__ ausgeben?

Code: Alles auswählen


def __add__(self,other):
                return tuple( (a+b for a,b in zip(self.value, other.value) ) )
                

def __sub__(self,other):
                return tuple( (a-b for a,b in zip(self.value, other.value) ) )
           
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

loyloep hat geschrieben:Mit welchen Befehlen ausser print lassen sich sich denn noch die Werte der Methode __add__ und __sub__ ausgeben?
Die Frage ergibt so überhaupt keinen Sinn - Was sind Werte einer Methode? Meinst du die Rückgabewerte, oder die Argumente? Oder die Methode selbst als (Funktions-)Objekt? Und Ausgeben geht mit allem, was eine Ausgabe produziert - vom simplen print (Ausgabe am STDOUT) über einen angeschlossenen Drucker, Modem, selbstgebasteltem LED-Modul am seriellen Port etc pp. Das ist sicher nicht was Du suchst...

Anscheinend hast Du ein paar Verständnislücken darüber, was ein Rückgabewert einer Funktion ist und was damit nach Rückgabe eigentlich passiert. Hierzu der Tipp: `obj.__add__(other)` ist gleichbedeutend zu `obj + other`. Wenn Du um letzteres Klammern setzt, wird vllt. klarer, wo der Rückgabewert landet.

Die Verkettung ala `a + b + c` funtioniert noch nicht mit Deinem Code, hier musst Du nochmal über den Typen Deines Rückgabewertes nachdenken.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

interessant ist, dass im (sehr guten) Buch "Fluent Python" genau das selber Beispiel drin ist und in verschiedenen Varianten durchgespielt wird. Und anderem, um __add__ und __sub__ zu erklären.

Ob der Aufgabensteller des TE da wohl abgeschrieben hat? ;-)

Gruß, noisefloor
Antworten