int nachbilden...

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
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

folgende Klasse verwende ich für x-Koordinaten:

Code: Alles auswählen

class X(object):
    def __init__(self, value, max_):
        self.value = value
        self.max_ = max_

    def __call__(self):
        return self.value

    def __add__(self, other):
        if self.value + other <= self.max_:
            self.value = self.value + other
        else:
            self.value = self.max_
        return self
Gibt es eine Möglichkeit, auf 'self.value' anstatt mit '__call__' direkt über den Exemplarnamen zuzugreifen, also in der Art:

Code: Alles auswählen

>>> x = X(0, 5)
>>> x #statt x()
0
>>> x += 3
>>> x #statt x()
3
So etwas wie '__str__', nur eben eine int als Rückgabe?

Gruß
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Wie wärs mit '__repr__'? Du erhältst dann allerdings keinen int, sollte aber für deinen Zweck ausreichend sein, wenn ich das richtig verstanden habe.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Gremlin:
Doch, ich benötige schon eine Zahl. Ich möchte mit dem X()-Exemplar wie mit einem int-Exemplar umgehen können. '__repr__' gibt mir ja einen String zurück...
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin,

du kannst von int ableiten:

Code: Alles auswählen

class X(int):
    def __new__(cls, value, max_):
        return int.__new__(cls, value)

    def __init__(self, value, max_):
        self.value = value
        self.max_ = max_

    def __call__(self):
        return self.value

    def __add__(self, other):
        if self.value + other <= self.max_:
            self.value = self.value + other
        else:
            self.value = self.max_
        return self
Edit: __add__, __iadd__, usw. müssen natürlich trotzdem entsprechend implementiert werden.

Gruß,
Manuel
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

mutetella hat geschrieben:So etwas wie '__str__', nur eben eine int als Rückgabe?
Verstehe ich dich richtig, dass beim Eintippen des Namens in der Konsole, statt deines X-Objektes ein Integer zurückgeben werden soll? Das hätte dann folgendes seltsames Verhalten zur Folge:

Code: Alles auswählen

>>> x = X(0,5)
>>> x
0
>>> i = x
>>> i is x
False
Glücklicherweise geht das nicht. Ich glaube du willst wirklich "__repr__" verwenden. Bei der Eingabe eines Namens in der Konsole wird immer das Objekt zurückgegeben. Wie es dargestellt wird, wird durch die Zeichenkette geregelt, die von "__repr__" zurückgeben wird.

Grüße
Gerrit
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@helduel:
Wenn ich von int ableite wäre X nicht mehr veränderbar. Ich suche eine Möglichkeit, nach außen eine Zahl zu repräsentieren, nach innen aber veränderbar zu sein.

@gkuhl:
Meine Erklärung hat da ein wenig zu kurz gegriffen. Es geht mir primär nicht darum, was in der Konsole bzw. per 'print' zurückkommt. Es geht mir darum, dass ich mit meinem X-Objekt umgehen kann, als wäre es eine Zahl.

Code: Alles auswählen

>>> x = X(1, 5)
>>> x
<X object at 0x2ae3710>
>>> i = x
>>> i is x
True
>>> x is 1
False    #Das ist mein Problem
>>> x.value is 1
True     #Das hätte ich gerne mit dem X-object!
Um es einmal so auszudrücken: Ich suche quasi nach einer '__type__'-Methode, die aufgerufen wird, wenn das X-object angefasst wird:

Code: Alles auswählen

...
    def __type__(self):
        return x.value
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
deets

@mutetella

1 is X ist ein Artefakt der Implementation von CPython, welches fuer gewisse Zahlen die dazugehoerigen PyObjects cached. Aber das ist kein Grund, das als Verhalten nachbilden zu wollen - zumindest sehe ich keinen, und du hast auch keinen motiviert.

1 == X hingegen kannst du mit Bordmitteln erreichen.

Wie waere es, wenn du uns mal erzaehlst, *wozu* das ganze gut sein soll? Es sieht naemlich so aus, als ob du dich da mal wieder ein bisschen in was reingesteigert hast ;)
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

mutetella hat geschrieben:@helduel:
Wenn ich von int ableite wäre X nicht mehr veränderbar. Ich suche eine Möglichkeit, nach außen eine Zahl zu repräsentieren, nach innen aber veränderbar zu sein.
Da habe ich dich nicht ganz verstanden. Ich würde aber trotzdem beim Ableiten von int bleiben (eine andere Möglichkeit sehe ich nicht). Du muss die __add__-Methode nur entsprechend anpassen, dann verhält sich die Klasse, wie du beschrieben hast. Naturlich mit dem Unterschied, dass du nach dem Addieren eine neue Instanz der Klasse bekommst und der Wert nicht in-place verändert wird. Das Resultat ist aber dasselbe:

Code: Alles auswählen

class X(int):
    def __new__(cls, value, max_):
        return int.__new__(cls, value)

    def __init__(self, value, max_):
        self.value = value
        self.max_ = max_

    def __call__(self):
        return self.value

    def __add__(self, other):
        value = self.value + other
        if value > self.max_:
            value = self.max_
        return X(value, self.max_)


>>> x = X(0, 5)
>>> x
0
>>> x += 3
>>> x
3
Gruß,
Manuel
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@deets:
Nachdem die x-Koordinate aufgrund verschiedenster Abhängigkeiten immer wieder neu berechnet werden muss, habe ich mir gedacht, das ganze der Übersichtlichkeit halber aus der eigentlichen Ansichtsklasse herauszulösen. Innerhalb der Ansichtsklasse möchte ich dann nicht mit 'self.x' oder 'self.x.value' oder 'self.x()' hantieren, sondern einfach mit 'self.x'...

Reine Eitelkeit...?

@helduel:
Ist es damit aber nicht so, dass ich nach unzähligen Neuberechnungen der x-Koordinate auch unzählige X-Exemplare 'herumgeistern' habe?


mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

mutetella hat geschrieben:@helduel:
Ist es damit aber nicht so, dass ich nach unzähligen Neuberechnungen der x-Koordinate auch unzählige X-Exemplare 'herumgeistern' habe?
Darum kümmert sich dann der Garbage Collector. Hat er schonmal was zu tun. :)

Gruß,
Manuel
deets

@mutetella

Fuer diesen Zweck ist aber deine Loesung doch nicht zwingend notwendig. Ich sehe eh nicht, wie die funktionieren kann, denn nehmen wir mal an, es gaebe ein __repr__-artiges Ding, was taete was du willst - wie wuerdest du es denn unterscheiden wollen, wann eine Koordinate ein int ist, und wann nicht? Denn dann muss konsequenterweise auch

self.x + 10

als Addition zweier Integers verstanden werden.

Ich sehe da 2 Loesungsmoeglichkeiten:

1) verlass dich einfach auf duck-typing. Dein x verhaelt sich wie ein int in den meisten Faellen, und wenn das reicht um dem Rest des Codes zu genuegen, dann bist du ja schon am Ziel.
2) abstrahier das spezialisierte Verhalten von Koordinaten weg von dem eignentlichn Wert der Koordinate hin zu den Manipulationen auf dem Objekt mit einer Koordinate, die du durchfuehrst.

Das waere eh meine favorisierte Loesung: ein Raumschiff, das ala Asteroids einen Screen-wrap-around machen soll, bewegst du einfach mit einer translate-Methode, und darin sorgst du schon dafuer, dass die Addition eben "wrappt". Und den direkten Zugriff via raumschiff.x = raumschiff.x + 10 solltest du halt nicht machen. Es kann ja eh von lauter Faktoren ausserhalb der Kenntnis der Koordinate selbst abhaengen, ob so eine Translation erfolgreich ist.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@deets:
:?:

Was könnte eine Koordinate denn anderes sein als ein int? Also ich habe lediglich vor, mich mit meinem x in einem curses.window hoch und runter zu bewegen. Nicht mehr und nicht weniger... :)
Und wenn ich Dein Raumschiff-Beispiel richtig verstehe, möchte ich eben genau das (nur eben nicht so umfangreich) mit meinem X-Objekt erreichen.

Ich bleibe jetzt einfach bei meinem X, das mir alle nötigen Methoden zur Koordinatenberechnung und -manipulation bietet. Und statt auf 'self.x' greife ich halt auf 'self.x.value' zu.

mutetella



... Hab' jetzt ein wenig geschaut, was so eine translate-Methode macht... Bin dabei unter anderem auf diesen Link gestoßen. Hat natürlich mit meinem curses.window, auf dem ich Text hin- und herscrollen möchte, nicht viel zu tun... aber das Prinzip scheint mir übertragbar... bin jedenfalls sehr aufgeregt...

Danke für die guten Anregungen!!
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten