OOP: Variable richtig in Funktion erstellen (mit Pygame)

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
Lennart4767
User
Beiträge: 7
Registriert: Dienstag 6. April 2021, 23:54

Guten Tag,
ich stehe aktuell vor einem Problem. Das ist ein grobes Beispiel, wie ich das meine.

Code: Alles auswählen

class A
	def 1(self, a)
		a = pygame.Rect()
class B
	def 2(self)
		A.1("rect1")
	def 3(self)
		if self.rect1.x >= 100:
			print("das Viereck ist bei 100")
B.2()
B.3()
Ich möchte halt eine Variable in einer Funktion erstellen, die ich danach (in einer anderen Funktion) noch benutzen kann. Es ist keine Option, die Variable woanders zu definieren, sondern soll in einer anderen Funktion, in einer anderen Klasse sein.
Der Fehler der immer auftaucht ist: 'B' object has no attribute 'rect1' , also dass rect1 nicht erkannt wird, sondern nur in der Funktion, wo es erstellt wird (def 1).
Ich habe schon rumprobiert und habe keine Lösung gefunden. Deswegen frage ich, ob mir jemand helfen könnte, oder ob das überhaupt möglich ist.
Vielen Dank schonmal
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Lennart4767,
Ich möchte halt eine Variable in einer Funktion erstellen, die ich danach (in einer anderen Funktion) noch benutzen kann
Um eine variable in einer anderen Funktion zu verwenden muss man sie einfach übergeben:

Code: Alles auswählen

def func_first():
    number = 10
    func_second(number)


def func_second(number):
    print(number)
Ob das jetzt Methoden einer Klasse sind oder freie Funktionen ist dabei erstmal egal.

Deine Fehlerbeschreibung verstehe ich leider nicht.
Es wäre einfacher, wenn du den tatsächlichen Code oder besser noch eine lauffähige Minimalversion posten könntest.
Da dein gezeigter Code sowieso nicht lauffähig ist hilft, er leider auch nicht bei der Fehleranalyse.
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Bitte beschreibe Dein wirkliches Problem und nicht, wie die von Dir erfundene "Lösung" in einer von Dir erfundenen Syntax nicht funktioniert. Wenn man etwas in einer Funktion benutzen will, muss man es als Argument übergeben.
Lennart4767
User
Beiträge: 7
Registriert: Dienstag 6. April 2021, 23:54

Ja okay, danke erstmal, das ist der richtige Code, wollte eigentlich oben nur probieren das Problem zu beschreiben, aber gut.
erste Funktion:

Code: Alles auswählen

 if self.cars_side_by_side_var1 == 1:
 	p.car_side1("moving_ad_car1", self.cars_spawn1, "ad_car1", self.var1[0])
 if self.cars_side_by_side_var1 == 2:
        p.car_side2("moving_ad_car1", self.cars_spawn1, "ad_car1", "moving_ad_car2", "ad_car2", self.var1[0])
 if self.cars_side_by_side_var2 == 1:
        p.car_side1("moving_ad_car11", self.cars_spawn3, "ad_car11", self.var1[1])
 if self.cars_side_by_side_var2 == 2:
        p.car_side2("moving_ad_car11", self.cars_spawn3, "ad_car11", "moving_ad_car12", "ad_car12", self.var1[1])
für erste Funktion noch p.car_side1 und p.car_side2:

Code: Alles auswählen

    
    def car_side1(self, a, b, c, d):
        a = pygame.Rect(random.choice(b), random.choice(g.car_lane), 220, 120)
        c = p.image(random.choice(g.car_type))
        c = pygame.transform.scale(c, (220, 120))
        d = 1

    def car_side2(self, a, b, c, d, e, f):
        a = pygame.Rect(random.choice(b), random.choice(g.car_lane), 220, 120)
        c = p.image(random.choice(g.car_type))
        c = pygame.transform.scale(c, (220, 120))

        d = pygame.Rect(random.choice(b), random.choice(g.car_lane), 220, 120)
        while a.colliderect(d):
            d = pygame.Rect(random.choice(b), random.choice(g.car_lane), 220, 120)
        e = p.image(random.choice(g.car_type))
        e = pygame.transform.scale(e, (220, 120))
        f = 2
        
zweite Funktion, möchte mit den Variablen moving_ad_car und ad_car arbeiten:

Code: Alles auswählen

if self.var1[0] >= 1:
                p.hitbox_crash(self.ad_car1, self.moving_ad_car1.x, self.moving_ad_car1.y, "hitbox11")
            if self.var1[0] >= 1:
                p.hitbox_crash(self.ad_car2, self.moving_ad_car2.x, self.moving_ad_car2.y, "hitbox12")
            if self.var1[1] >= 1:
                p.hitbox_crash(self.ad_car11, self.moving_ad_car11.x, self.moving_ad_car11.y, "hitbox13")
            if self.var1[1] >= 1:
                p.hitbox_crash(self.ad_car12, self.moving_ad_car12.x, self.moving_ad_car12.y, "hitbox14")
                
für zweite Funktion noch p.hitbox_crash:

Code: Alles auswählen

    def hitbox_crash(self, a, b, c, d):
        print(1)
        g.WIN.blit(a, (b, c))
        b -= g.VEL
        d = pygame.Rect(b + 15, c , 190, 120)
        if g.hitbox_main.colliderect(d):
            g.crash_active = True
das ist der original Code, ich hoffe, es ist lesbar.
Die zweite Funktion soll halt ad_car und moving_car benutzen, die aber oben in einer anderen Funktion übertragen werden. dabei kommt genau der Fehler: 'Game' object has no attribute 'ad_car1'.
Game (Abgekürzt mit g) ist dabei die 1. Klasse und Pieces (Abgekürzt mit p) ist die 2. Klasse, für die ganzen Bauteile quasi.
Anmerkung: p.image() ist eine Funktion zum einfügen von Fotos
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Lennart4767,

Der Fehler scheint in dieser Zeile in der zweiten Funktion aufzutreten:

Code: Alles auswählen

p.hitbox_crash(self.ad_car1, self.moving_ad_car1.x, self.moving_ad_car1.y, "hitbox11")
Warum das Attribut "ad_car1" für die Klasse nicht definiert ist und wie man es beheben könnte, kann ich an diesen Code-Bruchstücken aber leider nicht erkennen.
man sieht hier auch nicht wie die erste und zweite Funktion heißen und wie sie aufgerufen werden.
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Du benutzt sehr viele sehr schlechte Variablennamen. g und p, die besser game und Pieve heißen sollten, kommen aus dem Nichts. Ich rate mal, das sollten Attribute deiner Klasse sein. car_side1, car_side2 oder hitbox_crash benutzen self gar nicht. Ich vermute Du hast ein grundsätzliches Verständnisproblem, wie Funktionen funktionieren. Und wie Variablen funktionieren. Du hast Dir mit Deinem Spiel noch zu viel zugemutet. Gehe nochmal ein paar Schritte zurück und lerne erst einmal etwas über Variablen und Funktionen an einfachen Beispielen.
Lennart4767
User
Beiträge: 7
Registriert: Dienstag 6. April 2021, 23:54

Danke für die schnellen Antworten!
@rogerb
Das ding ist halt, ich kann nicht den ganzen Code rein stellen, da das 500 Zeilen Code sind und man den laufen lassen kann, weil man die dafür benötigten .png dateien noch braucht, trotzdem danke für deine Hilfe.

@Sirius3
Auch dir danke, ja ich bin kein Profi im programmieren, dennoch habe ich das Spiel schon komplett funktionsfähig geschrieben, allerdings halt nicht in OOP und schreibe es daher nur um. Ich danke dir trotzdem auch sehr.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn man Zustand ueber eine Methode einer Klasse hinaus aufbewaren will, dann benutzt man dazu die Instanz. Das ist ja genau der Sinn der Sache bei Objektorientierung. Und man kann bei einem hierarchischen Aufbau auch Unterobjekte mit Parametern aufrufen oder sogar mit der Instanz der Klasse darueber selbst.

Code: Alles auswählen

# ungetested und nur zur Illustration
class Bumper:

    def __init__(self, body_to_protect):
          self._body = body_to_protect

class RaceCar:
   def __init__(self, pos, size):
       self.bounding_box = rect.Rect(pos, size)
       self._rear_bumper = Bumper(self)
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@Lennart4767: ich schaue mal in meine Glaskugel und sehe, dass Du bisher viel mit globalen Variablen arbeitest. Ein erster Schritt, den Du gehen könntest, wäre es also, mit richtigen Funktionen anzufangen und die ganzen globalen Variablen zu beseitigen.
Auch scheinst Du viel mit durchnummierierten Variablennamen und kopiertem Code zu arbeiten. Das wäre auch eine Baustelle, an der Du Deine Fähigkeiten verbessern könntest, indem Du statt Nummern Listen und Schleifen verwendest.
Benutzeravatar
__blackjack__
User
Beiträge: 14056
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ergänzend zu Sirius3: Damit könntest/solltest Du vor dem umschreiben Richtung OOP anfangen. Wenn man globale Variablen beseitigt, muss zwischen den Funktionen mehr über Argumente und Rückgabewerte kommuniziert werden, und da sieht man dann manchmal auch besser welche Werte zusammengehören und man kann mit einfachen Datenklassen anfangen, was ja trotz Klassen auch immer noch prozedural ist. Wenn man die erst einmal hat, kann es leichter fallen auch Funktionalität aus den bisherigen Funktionen auf diese Objekte zu verschieben/aufzuteilen. Das ist ein etwas fliessenderer Übergang von prozedural nach objektorientiert.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten