Neue Operatoren definieren

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
spocksdata
User
Beiträge: 1
Registriert: Dienstag 30. Oktober 2012, 16:46

Hallo,
ich schreibe im Rahmen einer Projektarbeit für die Schule ein Programm zur Vektorrechnung und wollte meiner Vektor-Klasse noch ein paar Operatoren hinzufügen. Damit meine ich nicht , die Operatoren +,-,*,etc. zu überschreiben, sondern neue hinzufügen, wie zum Beispiel ein "x" für das Kreuzprodukt.
Gibt es einen Befehl für so etwas?
Viele Grüße,
spocksdata
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Nein.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Für solche "Spielerein" eignet sich Ruby eher.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

jbs hat geschrieben:Für solche "Spielerein" eignet sich Ruby eher.
In Ruby geht dass auch nicht.

In Haskell kann man aber neue Operatoren definieren und dass wird auch recht häufig genutzt.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Sorry, war da doch etwas zu sehr in Smalltalk denke :(

Wobei es da auch nicht ohne : geht.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

for the lulz:

Code: Alles auswählen

class Foo(object):
	def crossp(self, other):
		return other*2

class X(object):

	def __ror__(self, other1):
		self.other1 = other1
		return self

	def __or__(self, other2):
		return self.other1.crossp(other2)

x = X()
foo = Foo()

print foo |x| 21
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Immer wenn ich denke "... so langsam steig' ich durch ..." les' ich sowas und hab' nur noch ein "WOW!" auf dem Radar...
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ach das ist doch nicht mehr als die kreative Verwendung von links- und rechtsassoziativen Bitweisen Ors :D

Da muss man nicht durchsteigen, man sollte nur schon ein schweres Objekt suchen, das man dann schnell auf denjenigen zufuehrt, der sowas in Produktivcode einbaut und keine gute Erklaerung dafuer hat :twisted:
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Ok... ich meld' mich dann wieder bei Ihnen... :lol:
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
lunar

@cofi Warum eigentlich nicht? Eigentlich ist das nur eine Anwendung der klar definierten Sprachgrammatik. Operatoren in Haskell oder Scala sind nichts anderes ;)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Naja ich rede weniger von Operatoren-Ueberladung im Allgemeinen, sondern von dem Fall. Der Punkt ist ja die Anwendung einfacher und besser lesbar zu machen, aber hier braucht man ein spezielles Objekt und eine Syntax, die man nicht unbedingt mit einem Kreuzprodukt verbinden wuerde.

Ich wuerde jedenfalls zum schweren Objekt greifen :twisted:
BlackJack

Ausserdem hindert selbst die Schreibweise ohne Lehrzeichen nicht jeden daran ``print foo | x | 21`` zu lesen und zu verstehen — oder eben nicht zu verstehen. Ich würde jedenfalls denken `foo`, `x`, und 21 werden hier bitweise „Oder” verknüpft und der Autor hat nur PEP8 nicht gelesen. :-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mit ein paar Extrazeilen bekommt man das ganze auch noch ein wenig robuster und allgemeiner hin:

Code: Alles auswählen

import operator

class Operator(object):
    class _LeftOperator(object):
        def __init__(self, func, right):
            self.func = func
            self.right = right
        
        def __or__(self, left):
            return self.func(left, self.right)
            
    def __init__(self, func):
        self.func = func

    def __ror__(self, right):
        return Operator._LeftOperator(self.func, right)

def main():
    add = Operator(operator.add)
    
    print 1 |add| 2
    
    
if __name__ == "__main__":
    main()
Großflächig in einem Projekt einsetzen würde ich es wohl nicht. Problematisch finde ich, dass die ORs tatsächlich als OR gelesen werden können. Besonders dann, wenn man mal ein Leerzeichen einbaut. Die Sprache ist für solche Ausdrücke nicht ausgelegt daher sollte man mit dem Einsatz dieser Methode vorsichtig umgehen. bei Teilproblemen kann es aber durchaus praktisch sein um ein wenig Übersicht im Code zu gewinnen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mangels besseren Möglichkeiten würde ich wohl eher eine Methode `.X` implementieren, die das Kreuzprodukt errechnet und natürlich ein Argument annimmt. Könnte in der Anwendung dann so aussehen:

Code: Alles auswählen

(v1).X(v2)
Das erste Klammernpaar ist quasi ein Vorschlag für halbwegs konsistentes Design. ;)

Vielleicht möchte man `X` auch einfach nur so implementieren, dass es seinerseits nur die Methode `.crossproduct()` mit übergebenenm Argument aufruft, wo wiederrum die tatsächliche Berechnung geschieht. Das würde den Code lesbar halten und trotzdem eine gewisse Prägnanz für die Anwendung bei Berechnungen schaffen - auch wenn es nicht allzu schön aussieht.
Antworten