Klassen-Funktion an Variable binden

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
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

Hallo zusammen,

ich bin noch am Lernen der OOP und jetzt hat sich wieder eine Frage ergeben, wobei ich nicht mehr sicher bin, wie sinnvoll das eigentlich ist was ich da gerade versuche. Zur leichteren Erklärung habe ich alles auf ein Minimalbeispiel heruntergebrochen:
Ich habe eine Klasse erstellt, in der Objekte erstellt werden, die nur eine veränderbare Position besitzen. Da ich die Position nicht nur von einem Objekt sondern von allen ändern will, habe ich die Objekte in eine Liste gepackt, die dann an die entsprechenden Funktionen übergeben werden. Nun ist mir aber aufgefallen, dass in den Funktionen immer die fast identische for-Schleife steht, so dass ich diese Auslagern wollte, aber genau dort komme ich nicht weiter.
Ich hatte versucht die Klassen-Funktion an eine Variable zu binden, um diese dann über Objekt.Variable() aufrufen zu können, aber bekomme das nicht hin...

Code: Alles auswählen

class Objekte(object):
    def __init__(self, position):
        self.position = position
        
    def move_forward(self):
        self.position += 1
        
    def move_backward(self):
        self.position -= 1

    def get_position(self):
        return self.position
        
# Gruppenbewegung
def move_all_forward(objekt_liste):
#    for objekt in objekte_liste:		<--- erste Version
#           objekt.move_forward()
    move_all('forward', objekt_liste)

def move_all_backward(objekt_liste):
#    for objekt in objekte_liste:		<--- erste Version
#         objekt.move_backward()
    move_all('backward', objekt_liste)
	
def move_all(direction, objekt_liste):
	if direction == 'forward':
		move_function = move_forward  # <--- Fehler
	elif direction == 'backward':
		move_function = move_backward  # <--- Fehler
		
	for objekt in objekt_liste:
 	    objekt.move_function()    # <--- Aufruf

  
def main():
    objekt_liste = []
    objekt_1 = Objekte(8)
    objekt_liste.append(objekt_1)
    objekt_2 = Objekte(5)
    objekt_liste.append(objekt_2)
    
    print('objekt_1: {}'.format(objekt_1.get_position()))
    print('objekt_2: {}'.format(objekt_2.get_position()))
    print('---move all forward ---')
    move_all_forward(objekt_liste)
    print('objekt_1: {}'.format(objekt_1.get_position()))
    print('objekt_2: {}'.format(objekt_2.get_position()))
  
        
if __name__ == '__main__':
    main()
Oder würde man das eh völlig anders angehen?
Schonmal danke
BlackJack

@Zizibee: `Objekte` ist ein komischer Name für *ein* Objekt das *eine* Position kapselt.

Eine Möglichkeit (ungetestet):

Code: Alles auswählen

def move_all(direction, objects):
    for obj in objects:
        getattr(obj, 'move_' + direction)()

move_all_forward = partial(move_all, 'forward')
move_all_backward = partial(move_all, 'backward')
Mit `partial()` aus dem `functools`-Modul.
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,


brauchst du unbedingt ein forward und backward?
Vielleicht geht es ja auch so:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

class Objekte(object):
    def __init__(self, position=0):
        self.position = position
       
    def move(self, value=0):
        self.position += value

    def set(self, value=0):
        self.position = value

    def get_position(self):
        return self.position

   
def set_all(objekt_liste, value):
    for objekt in objekt_liste:
        objekt.set(value)

def move_all(objekt_liste, value):
    for objekt in objekt_liste:
        objekt.move(value)
 
def print_all(objekt_liste):
    for nr, objekt in enumerate (objekt_liste):
        print('objekt_liste[{}]: {}'.format(nr, objekt.get_position()))     

def main():
    objekt_liste = [ Objekte(8), Objekte(5) ]
    print_all(objekt_liste)
    
    print('---move all 1 forward ---')
    move_all(objekt_liste, 1)
    print_all(objekt_liste)

    print('---move all 2 backward ---')
    move_all(objekt_liste, -2)
    print_all(objekt_liste)

    print('---set all on postion 2 ---')
    set_all(objekt_liste, 2)
    print_all(objekt_liste)

if __name__ == '__main__':
    main()
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

BlackJack hat geschrieben:Mit `partial()` aus dem `functools`-Modul.
Danke für die Antwort, da bin ich jetzt am Einlesen.

@sebastian0202: Dir auch danke für die Antwort. Bei dem Beispiel könnte man es so machen, aber leider habe ich mein Beispiel wohl etwas zu minimal gehalten.

Eigentlich versuche ich als OOP Übung die Grundfunktionen es Rubik-Cubes / Zauberwürfel zu erstellen. Da wird es dann mit den ganzen Drehungen schon etwas komplizierter.
Vor langer Zeit hatte ich da schon mal mit C++ angefangen, allerdings ohne OOP und dafür mit einem dreidimensionalen Array. Das endete allerdings in dermaßen vielen IF-Bedingungen bei der Suche welche Farbe und damit welcher Stein wo sitzt, dass ich es jetzt mal so versuche. Ob das allerdings übersichtlicher ist, werde ich noch feststellen :D

Falls jemand dazu Kritik oder Anmerkungen hat, bin ich ganz Ohr :)
BlackJack

@Zizibee: Ich erinnere mich dunkel daran das ich auch schon mal einen Zauberwürfel modelliert habe. Ich hatte da für jede der sechs Seiten eine 2D-Datenstruktur und Methoden um einzelne Zeilen und Spalten auszulesen und zu setzen. Damit kann man dann die Rotationen von Zeilen und Spalten über den gesamten Würfel implementieren.
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@ BlackJack: Wenn du für jede der 6 Seiten eine Datenstruktur erstellt hast, dann musst du doch bei jeder Drehung 5 Datenstrukturen anpassen. Ist das nicht auch wieder etwas umständlich? (Nicht dass ich eine zufriedenstellende Lösung hätte)
BlackJack

@Zizibee: Wieso 5? Eine Drehung von einer Zeile oder Spalte betrifft doch immer nur vier Seiten‽ Und falls Du eine einfacher zu handhabende Struktur hast, dann her damit. :-)
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@BlackJack: Auf 4 Seiten wird etwas verschoben und die 5. wird um 90° gedreht.
Schön wärs... aber ich arbeite daran :wink:
BlackJack

@Zizibee: Oh, an die Seite hatte ich gar nicht gedacht. :oops: Macht das Programm IMHO aber nicht sehr viel komplexer. Man muss halt noch testen ob die Reihe oder Spalte aussen liegt und welche Seitenfläche dann die 90°-Drehung machen muss.
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@BlackJack: Ich finde die Grundfunktionen eines Würfels *kann* man recht einfach programmieren. Bei meinem ersten Versuch mit C++ hatte ich ein 5x5x5 Array, in dessen Mitte ich gedanklich den Würfel gelegt hatte. Damit konnte ich auf jeder Seite den inneren 9 Feldern Farbinformationen zuweisen. Also z.B. für eine komplett weiße Seite:

0|0|0|0|0
0|w|w|w|0
0|w|w|w|0
0|w|w|w|0
0|0|0|0|0

Das Drehen lief dann in Funktionen ab, die die Farbinformationen zwischen den Feldern verschoben haben.
Vom Prinzip her kann man das natürlich auch mit 6 3x3 Arrays realisieren, indem man sich den Würfel aufgeschnitten und flach vorstellt.

Was ich dabei nur etwas unterschätzt hatte, war der enorme Aufwand dann den Würfel zu lösen. Wollte ich z.B. einen bestimmten Eckstein suchen, musste ich 8 Ecksteine x 3 Seiten = 24 Felder nach einer bestimmten Farbe abfragen. Dann für jeden der 4 Treffer die Koordinaten für die anderen Seiten des Ecksteins raussuchen und mit dem Gesuchten vergleichen. Erst danach konnte ich anfangen für jede mögliche Position und Ausrichtung die Zugfolgen zu bestimmen.
Jetzt hatte ich *gehofft*, dass das mit dem OOP Ansatz etwas komfortabler geht, weil ich da direkt die Position der Steine abfragen kann. Falls nicht, sehe ich es als OOP Übung :wink:
BlackJack

@Zizibee: Letztendlich hast Du doch genau das selbe gemacht: einzelne Seiten modelliert. Nur das auf die dann, dadurch das sie in der 3D-Struktur stecken, komplizierter zugegriffen wird. Und das viele Stellen dieses 3D-Arrays leer sind und das doch auch immer bleiben werden, oder?
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@BlackJack: Richtig, genau so war es :D
Antworten