Gibt es hier nicht einen sozialen Menschen der für youtube o. ä. mal ein Tutorial zu OOP/Klassen machen möchte? :>
Allein durch lesen komm ich da nicht vorwärts .... und die momentanen Tutorials dazu sind eher 0 8 15
Gruß
Tengel
OOP Tutorial
Hm - Schnittstellen - wie genau das mit dem Globalen Zugriff ist.
self bedeutet ja ein Objekt- der Klasse, oder eine Instanz? oder ist das dass selbe?
Wann genau muss ich mit other Arbeiten? Nur wenn es dabei um ein anderes Klassenobjekt geht? Muss das von der selben Klasse sein?
Warum war an meinem Gui falsch das in der gui die commands für die Trafficobjekte gegeben wurde? Wie soll das sonst gehen?
Wieso kommt die Stapelklasse an die Attribute einer anderen Klasse?
self bedeutet ja ein Objekt- der Klasse, oder eine Instanz? oder ist das dass selbe?
Wann genau muss ich mit other Arbeiten? Nur wenn es dabei um ein anderes Klassenobjekt geht? Muss das von der selben Klasse sein?
Warum war an meinem Gui falsch das in der gui die commands für die Trafficobjekte gegeben wurde? Wie soll das sonst gehen?
Code: Alles auswählen
class Karte():
def __init__(self, farbe=0, rang=2):
self.farbe = farbe
self.rang = rang
farb_namen = ["Kreuz", "Karo", "Herz", "Pik"]
rang_namen = [None, "Ass", "2", "3", "4", "5", "6", "7", "8","9",
"10", "Bube", "Dame", "König"]
def __str__(self):
return Karte.farb_namen[self.farbe] + "-" + Karte.rang_namen[self.rang]
def __cmp__(self, other):
if self.farbe > other.farbe: return 1
if self.farbe < other.farbe: return -1
if self.rang > other.rang: return 1
if self.rang < other.rang: return -1
return 0
class Stapel():
def __init__(self):
self.karten = [ ]
for farbe in range(4):
for rang in range(1,14):
karte = Karte(farbe, rang)
self.karten.append(karte)
def __str__(self):
res = [ ]
for karte in self.karten:
res.append(str(karte))
return "\n".join(res)
def ziehe_karte(self):
return self.karten.pop()
self bedeutet erst einmal gar nichts. self wird aber per Konvention als Bezeichnername für den ersten Parameter einer Methode verwendet und enthält bei der Verwendung dann ein Exemplar (Instanz) der Klasse.Tengel hat geschrieben:self bedeutet ja ein Objekt- der Klasse, oder eine Instanz? oder ist das dass selbe?
Auch other ist nur ein Name. Welches Objekt daran gebunden wird ist beliebig, allerdings wird dieser Bezeichnername tatsächlich häufig innerhalb der Parameterliste von Methoden verwendet wenn eine zweite Instanz übergeben wird.Tengel hat geschrieben:Wann genau muss ich mit other Arbeiten? Nur wenn es dabei um ein anderes Klassenobjekt geht? Muss das von der selben Klasse sein?
Warum nicht? Genau darum geht es doch. Oder möchtest du Attribute schützen? Dann versieh deren Namen mit einem führenden Unterstrich und das ist dann ein Hinweis, dass es sich hier um ein Attribut handelt das nicht als öffentlicher Teil der Klasse betrachtet werden soll.Tengel hat geschrieben:Wieso kommt die Stapelklasse an die Attribute einer anderen Klasse?
Also selbst wenn ich self.xyz Werte in der Methode nicht durch return zurück gebe kann global darauf zugegriffen werden?
Bzw. wundert es mich ja das die Stapel Klasse auf rang und farb Zuweisung zugreifen kann obwohl ich die Klasse ja nur geschrieben hab - also ohne in der Main auch wirklich ein Objekt zuzuweisen.
Bzw. wundert es mich ja das die Stapel Klasse auf rang und farb Zuweisung zugreifen kann obwohl ich die Klasse ja nur geschrieben hab - also ohne in der Main auch wirklich ein Objekt zuzuweisen.
Zuletzt geändert von Tengel am Freitag 26. April 2013, 13:34, insgesamt 1-mal geändert.
Was soll global heißen? Wenn man Zugriff auf das Klassen-Exemplar hat, dann kann man auch auf diese Variablen zugreifen. Kannst dir auch mal die Übersetzung des offiziellen Tutorials anschauen.Tengel hat geschrieben:Also selbst wenn ich self.xyz Werte in der Methode nicht durch return zurück gebe kann global darauf zugegriffen werden?
Zuletzt geändert von nomnom am Freitag 26. April 2013, 13:37, insgesamt 1-mal geändert.
Ja. Auf jedes Attribut, das an ein Objekt gebunden ist, kann von überall her zugegriffen werden, ohne dass irgendwelche Beschränkungen bestehen. Sowas kann man übrigens auch leicht durch eigene Experimente (Testprogramm oder Python-Shell) herausfinden, bevor man solche Fragen stellt.
@Tengel: Man muss ein bisschen vorsichtig mit den Begriffen sein, weil in Python Klassen auch Objekte sind. Die Attribute einer Klasse sind die Attribute auf dem Klassenobjekt, was nicht das gleiche ist wie die Attribute auf dem Exemplar (Instanz) einer Klasse. Allerdings sind die Klassenattribute auch über das Exemplar erreichbar, sofern sie auf dem Exemplar nicht durch ein Attribut auf dem Exemplar verdeckt werden:
In `Stapel` wird doch gar nicht auf Attribute von `Karte` zugegriffen, weder auf die von der Klasse noch die eines Exemplars. Jedenfalls nicht direkt.
Anmerkungen zum Quelltext: Namen von Klassenattributen schreibe ich persönlich komplett in Grossbuchstaben wenn es sich um Konstanten handelt.
Die Default-Werte bei den Argumenten von `__init__()` würde ich weg lassen, denn ich sehe nicht was an einer Kreuz 2 so besonders ist, dass das die Karte ist, die jeder erwarten würde wenn man die Argumente weg lässt.
Die `__cmp__()` kann man mit Tupeln der Daten die eine Karte ausmachen und der `cmp()`-Funktion wesentlich einfacher machen. Wenn man `__cmp__()` (oder `__eq__()`) implementiert, sollte man insbesondere bei Wertdatentypen auch die `__hash__()`-Methode implementieren. Wertdatentypen sind solche, bei denen die Attribute, die den Gesamtwert des Objekts ausmachen, sich nicht mehr ändern. Eine passende `__hash__()`-Implementierung braucht man um die Objekte als Schlüssel in Wörterbüchern oder Elemente in `set()`\s zu speichern. Die Wertigkeit von Farbe und Rand beim Vergleich würde ich übrigens umdrehen.
Der `Stapel` weiss IMHO zu viel über die Karten weil er das Kartenspiel in der `__init__()` erstellt. Man könnte einen Kartenstapel schreiben ohne dass der etwas darüber wissen muss wie die einzelnen Karten aussehen. Also einen der für Karten mit Farbe und Rang genau so funktioniert, wie für UNO-Karten, oder Quartett, oder andere Kartenarten.
Das erzeugen eines Kartenspiels wäre robuster, wenn es sich an den Rang- und Farbdaten orientieren würde, statt die Anzahlen hart als Zahlen in den Quelltext zu schreiben. Wenn man ein Romme-Spiel erzeugen möchte, müsste man sowohl die Liste mit den Rängen, als auch die Anzahl der Schleifendurchläufe anpassen, statt nur die Ränge.
Code: Alles auswählen
class A(object):
a = 42
b = 23
def __init__(self):
self.b = 4711
print A.a # 42
print A.b # 23
a = A()
print a.a # 42
print a.b # 4711
Anmerkungen zum Quelltext: Namen von Klassenattributen schreibe ich persönlich komplett in Grossbuchstaben wenn es sich um Konstanten handelt.
Die Default-Werte bei den Argumenten von `__init__()` würde ich weg lassen, denn ich sehe nicht was an einer Kreuz 2 so besonders ist, dass das die Karte ist, die jeder erwarten würde wenn man die Argumente weg lässt.
Die `__cmp__()` kann man mit Tupeln der Daten die eine Karte ausmachen und der `cmp()`-Funktion wesentlich einfacher machen. Wenn man `__cmp__()` (oder `__eq__()`) implementiert, sollte man insbesondere bei Wertdatentypen auch die `__hash__()`-Methode implementieren. Wertdatentypen sind solche, bei denen die Attribute, die den Gesamtwert des Objekts ausmachen, sich nicht mehr ändern. Eine passende `__hash__()`-Implementierung braucht man um die Objekte als Schlüssel in Wörterbüchern oder Elemente in `set()`\s zu speichern. Die Wertigkeit von Farbe und Rand beim Vergleich würde ich übrigens umdrehen.
Der `Stapel` weiss IMHO zu viel über die Karten weil er das Kartenspiel in der `__init__()` erstellt. Man könnte einen Kartenstapel schreiben ohne dass der etwas darüber wissen muss wie die einzelnen Karten aussehen. Also einen der für Karten mit Farbe und Rang genau so funktioniert, wie für UNO-Karten, oder Quartett, oder andere Kartenarten.
Das erzeugen eines Kartenspiels wäre robuster, wenn es sich an den Rang- und Farbdaten orientieren würde, statt die Anzahlen hart als Zahlen in den Quelltext zu schreiben. Wenn man ein Romme-Spiel erzeugen möchte, müsste man sowohl die Liste mit den Rängen, als auch die Anzahl der Schleifendurchläufe anpassen, statt nur die Ränge.
Code: Alles auswählen
from itertools import imap
from random import shuffle
class Karte(object):
FARB_NAMEN = ['Kreuz', 'Karo', 'Herz', 'Pik']
RANG_NAMEN = [
'Ass', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Bube', 'Dame',
'König',
]
def __init__(self, farbe, rang):
self.farbe = farbe
self.rang = rang
def __str__(self):
return self.FARB_NAMEN[self.farbe] + '-' + self.RANG_NAMEN[self.rang]
def as_tuple(self):
return (self.rang, self.farbe)
def __cmp__(self, other):
return cmp(self.as_tuple(), other.as_tuple())
def __hash__(self):
return hash(self.as_tuple())
@classmethod
def erzeuge_kartenspiel(cls):
return Stapel(
[
cls(f, r)
for f in xrange(len(cls.FARB_NAMEN))
for r in xrange(len(cls.RANG_NAMEN))
]
)
class Stapel(object):
def __init__(self, karten):
self.karten = karten
def __str__(self):
return '\n'.join(imap(str, self.karten))
def mischen(self):
shuffle(self.karten)
def ziehe_karte(self):
return self.karten.pop()
def main():
stapel = Karte.erzeuge_kartenspiel()
stapel.mischen()
print stapel
print stapel.ziehe_karte()
if __name__ == '__main__':
main()
@Tengel: Das sind doch keine Attribute von `Karte`‽ Attribute sind die Dinger wo man mit dem Punktoperator drauf zugreift. Die Schleifenvariablen haben halt die gleichen Namen wie die Attribute, wegen der gleichen Bedeutung, aber man könnte die auch komplett anders nennen. Wäre nur nicht so sinnvoll.
Aber selbst wenn man tatsächlich auf die Attribute zugreifen würde, das tut man doch *ständig* wenn man den Punktoperator verwendet. Und wie schon erwähnt wurde: Wenn man das nicht machen soll(te), dann stellt der Programmierer dem Attributnamen einen Unterstrich voran.
Aber selbst wenn man tatsächlich auf die Attribute zugreifen würde, das tut man doch *ständig* wenn man den Punktoperator verwendet. Und wie schon erwähnt wurde: Wenn man das nicht machen soll(te), dann stellt der Programmierer dem Attributnamen einen Unterstrich voran.