Objektorientiertes Programmieren

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.
Sconine
User
Beiträge: 49
Registriert: Montag 1. Juni 2009, 11:00

Hallo zusammen,

ich habe ein Programm zum objektorientiertes Programmieren geschrieben. Ein Quadrat soll gezeichnet, gelöscht veschschoben und skaliert werden. Dann soll noch der Umfang und Inhalt berechnet werden.

class quadrat:
def __init__(self,seitenlaenge,zentrum):
self.seitenlaenge = seitenlaenge
self.zentrum = zentrum
return

def anzeigen(self):
from turtle import *
angle = 90
color("white")
setx(self.zentrum[0]-0.5*self.seitenlaenge)
sety(self.zentrum[1]-0.5*self.seitenlaenge)
color("black")
for i in range(4):
forward(self.seitenlaenge)
left(angle)
return

def loeschen(self):
from turtle import *
color("white")
angle = 90
for i in range(4):
forward(self.seitenlaenge)
left(angle)
return

def verschieben(self,neues_zentrum):
from turtle import *
self.loeschen()
color("white")
self.zentrum = neues_zentrum
self.anzeigen()
return

def skalieren(self,faktor):
self.loeschen()
self.seitenlaenge *= faktor
self.anzeigen()
return

def umfang(self,seitenlaenge):
U = 4*self.seitenlaenge
print U
return

def inhalt(self,seitenlaenge):
A = self.seitenlaenge**2
print A
return


square = quadrat(50,(0,0))
square.anzeigen()
Umfang = square.umfang(50)
Inhalt = square.inhalt(50)
square.verschieben((150,150))
square.skalieren(3)

Ich habe Probleme, wenn ich nach dem Verschieben das Quadrat um den ersten Zentrum herum skalieren möchte.

Kann mir da jemand weiterhelfen????

Vielen Dank

[/code]
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

hallo :D

setzt bitte noch einen code-tag an den anfang des codes:

Code: Alles auswählen


das forum hat übrigens eine vorschau-funktion.
Zuletzt geändert von Dill am Mittwoch 10. Juni 2009, 10:14, insgesamt 1-mal geändert.
http://www.kinderpornos.info
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

du müsstest deinen Code noch in Code-Tags packen, so kann man ihn nur sehr schlecht lesen. Aber einige Tipps schon mal im Voraus:

- riskiere mal einen Blick in PEP8 bzgl. der Klassen- und Variablennamen und Leerzeichen zwischen den Parametern einer Funktion.
- "return"s ohne einen Rückgabewert am Ende einer Methode/Funktion sind überflüssig.
- mache keine *-Importe. Dass ist unübersichtlich und führt sehr leicht zu Fehlern. Schreibe also besser "import turtle" und rufe dann die Funktionen mit "turtle.color(...)" auf. Wenn ein Modulname mal zu lang ist, dann geht auch "import turtle as trtl".
- da die Importe von Turtle überall benötigt werden solltest du diese am Anfang des Scripts machen und nicht jedes Mal wenn eine Methode aufgerufen wird.
Das Leben ist wie ein Tennisball.
Sconine
User
Beiträge: 49
Registriert: Montag 1. Juni 2009, 11:00

Code: Alles auswählen


class quadrat:
    def __init__(self,seitenlaenge,zentrum):
        self.seitenlaenge = seitenlaenge
        self.zentrum = zentrum
        return
    
    def anzeigen(self):
        from turtle import *
        angle = 90
        color("white")
        setx(self.zentrum[0]-0.5*self.seitenlaenge)
        sety(self.zentrum[1]-0.5*self.seitenlaenge)
        color("black")
        for i in range(4):
            forward(self.seitenlaenge)
            left(angle)
        return
    
    def loeschen(self):
        from turtle import *
        color("white")
        angle = 90
        for i in range(4):
            forward(self.seitenlaenge)
            left(angle)
        return
    
    def verschieben(self,neues_zentrum):
        from turtle import *
        self.loeschen()
        color("white")
        self.zentrum = neues_zentrum
        self.anzeigen()
        return
    
    def skalieren(self,faktor):
        self.loeschen()
        self.seitenlaenge *= faktor
        self.anzeigen()
        return

    def umfang(self,seitenlaenge):
        U = 4*self.seitenlaenge
        print U
        return

    def inhalt(self,seitenlaenge):
        A = self.seitenlaenge**2
        print A
        return
    

square = quadrat(50,(0,0))
square.anzeigen()
Umfang = square.umfang(50)
Inhalt = square.inhalt(50)
square.verschieben((150,150))
square.skalieren(3)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Und jetzt noch das berücksichtigen, was EyDu geschrieben hat ... :wink:
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

Ich habe Probleme, wenn ich nach dem Verschieben das Quadrat um den ersten Zentrum herum skalieren möchte.
was meinst du damit?
du verschiebst das quadrat, es wird an der neuen position gezeichnet,
dann skalierst du, es wird um dieses zentrum herum gezeichnet. was erwartest du, ist doch schön so.

ich finde es übrigens ok bei turtle mit import * zu arbeiten.
es schadet aber natürlich auch nicht wenn du es dir direkt "richtig" angewöhnst.
wenn du später mehr module (hier ja nur turtle) importierst, kommst du nicht durcheinander und du läufst nicht gefahr funktionalität des moduls zu überschreiben. wenn du in deinem code zb eine "clear"-funktion schreibst, kannst du die von turtle nicht mehr benutzen, weil sie "verdeckt" ist.

die anderen hinweise solltest du aber auf jeden fall umsetzen.

du hättest übrigens auch einfach "edit" clicken können, statt eine neue antwort zu posten.
http://www.kinderpornos.info
BlackJack

@Sconine: Bei Umfang und Inhalt werden Argumente übergeben, die gar nicht verwendet werden. Und statt dem ``print`` sollte man das Ergebnis besser zurückgeben, damit man mit den Methoden mehr anfangen kann, als nur auf der Konsole auszugeben.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Importe gehören außerdem nach oben und nicht in jeden Methodenaufruf der Klasse. Des Weiteren kann man `angle` als Klassenattribut zuweisen, um auch hier Wiederholungen zu vermeiden.
BlackJack

@snafu: Du meinst wohl als Attribut auf dem Exemplar. Bei der Klasse hätten dann ja alle den gleichen Winkel. :-)
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

was aber bei einem Quadrat nicht weiter schlimm wäre...
schon fast genial 8)
http://www.kinderpornos.info
BlackJack

Hach ja, ich hätte auch mal in den Quelltext schauen sollen. :oops: Ich nahm an, es ging um den Winkel, in dem das Quadrat angezeigt wird, und nicht den Winkel zwischen den Kanten.
Sconine
User
Beiträge: 49
Registriert: Montag 1. Juni 2009, 11:00

Vielen Dank für die Tipps.

Ich habe nun den import turtle an den Anfang gestellt und bei jeder Methode turtle.color(...) aufgerufen:

Code: Alles auswählen

import turtle

class Quadrat:
    def __init__(self,seitenlaenge,zentrum):
        self.seitenlaenge = seitenlaenge
        self.zentrum = zentrum
        return
    
    def anzeigen(self):
        angle = 90
        turtle.color("white")
        setx(self.zentrum[0]-0.5*self.seitenlaenge)
        sety(self.zentrum[1]-0.5*self.seitenlaenge)
        turtle.color("black")
        for i in range(4):
            forward(self.seitenlaenge)
            left(angle)
        return
    
    def loeschen(self):
        turtle.color("white")
        angle = 90
        for i in range(4):
            forward(self.seitenlaenge)
            left(angle)
        return
    
    def verschieben(self,neues_zentrum):
        self.loeschen()
        turtle.color("white")
        self.zentrum = neues_zentrum
        self.anzeigen()
        return
    
    def skalieren(self,faktor):
        self.loeschen()
        self.seitenlaenge *= faktor
        self.anzeigen()
        return

    def umfang(self,seitenlaenge):
        U = 4*self.seitenlaenge
        print U
        return

    def inhalt(self,seitenlaenge):
        A = self.seitenlaenge**2
        print A
        return
    

square = quadrat(50,(0,0))
square.anzeigen()
Umfang = square.umfang(50)
Inhalt = square.inhalt(50)
square.verschieben((150,150))
square.skalieren(3)
Als Fehlermeldung bekomme ich jetzt:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:/Python25/Eigene/Aufgabe_turtle.py", line 53, in <module>
    square.anzeigen()
  File "C:/Python25/Eigene/Aufgabe_turtle.py", line 12, in anzeigen
    setx(self.zentrum[0]-0.5*self.seitenlaenge)
NameError: global name 'setx' is not defined
Was habe ich denn jetzt falsch gemacht? Warum ist jetzt setx nicht definiert???

Ich tue mich sehr schwer mit Python, also bitte antworten, als ob ich ein 3 jähriges Kind wäre. :D
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Sconine hat geschrieben:Ich habe nun den import turtle an den Anfang gestellt und bei jeder Methode turtle.color(...) aufgerufen:
[...]

Was habe ich denn jetzt falsch gemacht? Warum ist jetzt setx nicht definiert???

Ich tue mich sehr schwer mit Python, also bitte antworten, als ob ich ein 3 jähriges Kind wäre. :D
Warum probierst du das, was du bei color (turtle.color) ausprobiert hast, nicht auch mal bei setx aus?
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

vorher hattest du ja alles (funktionen, klassen, konstanten) aus dem modul turtle importiert:

Code: Alles auswählen

from turtle import *
damit waren die funktionen aus turtle direkt verfügbar, zb setx().

jetzt importierst du nicht alles aus turtle, sondern das modul turtle.
die funktionen usw sind jetzt so zu erreichen:

Code: Alles auswählen

turtle.setx()
du hast jetzt also einen weiteren "namesraum", nämlich "turtle".

du musst jetzt vor alle turtle funktionen "turtle." schreiben. (wie du es ja bei color schon gemacht hast)
http://www.kinderpornos.info
Sconine
User
Beiträge: 49
Registriert: Montag 1. Juni 2009, 11:00

Also so funktioniert es jetzt:

Code: Alles auswählen

import turtle

class Quadrat:
    def __init__(self,seitenlaenge,zentrum):
        self.seitenlaenge = seitenlaenge
        self.zentrum = zentrum
        return
    
    def anzeigen(self):
        angle = 90
        turtle.color("white")
        turtle.setx(self.zentrum[0]-0.5*self.seitenlaenge)
        turtle.sety(self.zentrum[1]-0.5*self.seitenlaenge)
        turtle.color("black")
        for i in range(4):
            turtle.forward(self.seitenlaenge)
            turtle.left(angle)
        return
    
    def loeschen(self):
        turtle.color("white")
        angle = 90
        for i in range(4):
            turtle.forward(self.seitenlaenge)
            turtle.left(angle)
        return
    
    def verschieben(self,neues_zentrum):
        self.loeschen()
        turtle.color("white")
        self.zentrum = neues_zentrum
        self.anzeigen()
        return
    
    def skalieren(self,faktor):
        self.loeschen()
        self.seitenlaenge *= faktor
        self.anzeigen()
        return

    def umfang(self,seitenlaenge):
        U = 4*self.seitenlaenge
        print U
        return

    def inhalt(self,seitenlaenge):
        A = self.seitenlaenge**2
        print A
        return
    

square = Quadrat(50,(0,0))
square.anzeigen()
Umfang = square.umfang(50)
Inhalt = square.inhalt(50)
square.verschieben((150,150))
square.skalieren(3)
Und jetzt kann ich die "leeren" returns weglassen?
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

ja, die kannst du weglassen. die bewirken nur, dass die funktion verlassen wird. aber da die immer am ende der funktionen stehen haben sie keinerlei wirkung. return brauchst du wenn die funktion was zurückgeben soll.

Code: Alles auswählen

def addiere(a, b):
   return a + b
und deinen testcode am ende solltest du ergänzen mit:

Code: Alles auswählen

if __name__ == "__main__":
    square = Quadrat(50,(0,0)) 
    square.anzeigen() 
    (...)
dann kannst du dein quadrat.py oder wie du die datei nennst in einem anderen script benutzen mit:

Code: Alles auswählen

import quadrat
ohne dass der testcode aufgerufen wird.
kannst das ja mal probieren und evtl noch ein "print __name__" in den testcode einfügen und schauen was passiert wenn du das script direkt startest und wenn du es importierst.
Zuletzt geändert von Dill am Mittwoch 10. Juni 2009, 17:23, insgesamt 1-mal geändert.
http://www.kinderpornos.info
Sconine
User
Beiträge: 49
Registriert: Montag 1. Juni 2009, 11:00

VIELEN DANK.

So kann ich es beruhigt abgeben. :D
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

EyDu hat geschrieben: - riskiere mal einen Blick in PEP8 bzgl. der Klassen- und Variablennamen und Leerzeichen zwischen den Parametern einer Funktion.
wenn dus wirklich schön machen willst, könntest du dir das noch zu herzen nehmen.
http://www.kinderpornos.info
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Besser als "leere returns" wegzulassen ist es, die print-Anweisung aus den Methoden zu verbannen und stattdessen "volle returns" zu verwenden.

Was umfang() und inhalt() angeht, so wäre es passender, keine Seitenlänge zu übergeben, weil es ja Methoden eines Quadrat-Objekts sind, was zu jedem Zeitpunkt schon eine bestimmte Seitenlänge hat.

Ich würde sogar noch weitergehen und dafür gar keine Methode verwenden, sondern es in Datenattributen ablegen, die jeweils beim Skalieren neu berechnet werden.

Nimmt man statt turtle das frog-Modul, dann könnte das ganze so aussehen:

Code: Alles auswählen

from frog import Pool, Frog

class Quadrat(Frog):

    def __init__(self,tafel,seite=50):
        Frog.__init__(self, tafel)
        self.seite = seite
        self.skaliere(1)

    def verschiebe(self, *zentrum):
        self.pos = zentrum

    def loesche(self):
        self.exit()

    def skaliere(self, faktor):
        self.seite *= faktor
        self.umfang = 4*self.seite
        self.flaeche = self.seite ** 2
        self.shape = (0,0), (self.seite,0), (self.seite,self.seite), (0,self.seite), (0,0)

tafel = Pool()
quad1 = Quadrat(tafel)
quad1.verschiebe(40,50)
quad2 = Quadrat(tafel, seite=40)
quad2.color = "red"
quad2.verschiebe(-50,-30)
quad2.skaliere(2)
print quad2.flaeche
print quad1.umfang
quad1.loesche()
tafel.ready()

Hast du Python >= 2.6, dann sollte das mit dem turtle-Modul ähnlich gehen. Hast du noch Python <= 2.5, dann hast du noch die alte, magere turtle-Fassung. Mit der kommt nicht so viel Freude auf. Dann entweder Python auf eine aktuellere Version bringen oder xturtle einsetzen. (Oder den Frosch)
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

numerix hat geschrieben:Besser als "leere returns" wegzulassen ist es, die print-Anweisung aus den Methoden zu verbannen und stattdessen "volle returns" zu verwenden.
die hab ich garnicht gesehen, ja das solltest du ändern, also:

Code: Alles auswählen

(...)
def berechne_umfang(self):
   return 4 * self.seitenlaenge

print mein_quadrat.berechne_umfang()
also da stecken doch noch ein paar probleme in dem code:
- bei einigen methoden übergibst du nutzlose variablen. (ist dir klar warum die nicht notwendig ist bei umfang?)
- die methodennamen sollten verben sein
- nicht englisch und deutsch mischen (daher habe ich jetzt mal das quadrat statt square "mein_quadrat" genannt.

und vergleich mal den code von numerix mit deinem, das könnte lehrreich sein. (obwohl der sich auch nicht wirklich an pep8 hält :cry: )
verstehst du was bei ihm mit den ganzen methoden wie umfang() passiert ist?
http://www.kinderpornos.info
Antworten