Seite 2 von 2

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 11:11
von snafu
Und im Hinblick auf den "Register-Quatsch" hatte ich ja schon im Code angedeutet, dass man die Registierung der Gebäudetypen in __init__ als Dictionary Comprehension per Einzeiler abfrühstücken kann. Eine nachträgliche Registrierung von Gebäudetypen während des Spiels ist doch sowieso unrealistisch. Oder geht es um die Freischaltung weiterer Gebäudetypen? Dann würde ich das wahrscheinlich eher über ein activated-Atrribut lösen. Denn ich kenne es so, dass Gebäude aus höheren Stufen zunächst ausgegraut sind. Dass ein angefangenes Spiel plötzlich komplett neue Gebäudetypen erhält, habe ich bisher noch nicht gesehen. Wenn das irgendwann möglich sein soll, dann wäre eine Plugin-API für diesen Punkt vielleicht geeigneter.

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 11:19
von snafu
kbr hat geschrieben:
snafu hat geschrieben:Also wie schon vorgeschlagen wurde, ruhig zu Beginn ein paar Containerklassen definieren, jeweils für Koordinaten, Feldinfo und sowas.
Noch eine Stufe vorher empfehle ich ein großes Blatt Papier, einen Bleistift, sowie einen *großen* Radiergummi. :)
Wobei man IMHO schon viel Erfahrung braucht, um so ein Projekt quasi auf dem Papier durchplanen zu können. Der OP kommt mir so vor als wenn er zwar nicht gänzlich neu auf dem Feld der Programmierung ist, aber noch recht am Anfang bei der Progammierung komplexer Spiele steht. Vieles ist dann auch einfach Learning By Doing mit dem häufigen auf die Nase fallen inklusive.

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 11:39
von kbr
snafu hat geschrieben:Wobei man IMHO schon viel Erfahrung braucht, um so ein Projekt quasi auf dem Papier durchplanen zu können.
Etwas im Vorfeld fehlerfrei durchplanen zu können halte ich für unrealistisch. Es geht vielmehr darum einen Einstieg zu finden, der einem später möglichst wenig Kopfschmerzen bereitet. Ohne Plan zu starten ist schlecht - selbst bei agiler Entwicklung :)

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 14:54
von Pygoscelis papua
Also das Blatt Papier existiert schon :D
Ich habe: - eine Liste Für die meilensteine,
- ein Klassendiagramm
- ein Groben schriftlichen Text für die Anforderungen
- einen Plan für die Graphische Oberfläche

Und die Änderungen von Snafu sind auch schon übernommen,
die Registrierung ist jetzt eben nicht mehr in der Game-Klasse sondern in dem building_types.py Modul, von welchem man das importieren kann.
Den Rest schaue ich mir heute mal an.
Vieleicht habe ich in letzter Zeit zu viel lua und pascal programmiert und muss mich in Python erst wieder reinfinden :)

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 18:17
von Pygoscelis papua
Ich bin gerade noch dabei die Anmerkungen welche ihr mir gegeben habt um zu setzten.
Dabei ist aber etwas sehr seltsames passiert. Ich habe die klasse Planet wie folgt definiert:

Code: Alles auswählen

class Planet():
    def __init__(self, position, size):
        self.position = position
        self.size = size
        self.map = [
            [MapField((x, y), ground_types["G"]) for x in range(size)] 
            for y in range(size)
        ]
        print(type(self))
 
    def __repr__(self):
        class_name = type(self).__name__
        x, y = self.position
        return '{}(x={}, y={})'.format(class_name, x, y)
 
    def place_commando_center(self, owner):
        position = _randpos(self.size)
        return self.build_building(position, "Commando Center", owner)
 
    def has_commando_center(self, player): #must be tested!
        return any(
            field.get_owner() == player and 
            isinstance(field.get_building(), CommandoCenter)
            for field in self._get_all_fields()
        )
        
    def get_field(self, position):
        x, y = position
        return self.map[x][y]
   
    def set_ground(self, position, ground):
        field = self.get_field(position)
        field.set_ground(ground)

    def build_building(self, position, building_name, owner):
        field = self.get_field(position)
        return field.build_building(self, building_name, owner)

    def _show(self):
        print(self)
        print('\n'.join([str(i) for i in self.map]))

    def _get_all_fields(self):
        return [field for row in self.map for field in row]
und jetzt wird mir immer der __name__ von allen Planet-instanzen auf "instance" gesetzt, wobei die Methoden gleich verwendet werden können.
Das bedeutet die ausgabe von planetinstance.__repr__() ist dann "instance{x=..., y=...}".
wie kann das passiert sein?

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 19:55
von Kebap
Pygoscelis papua hat geschrieben:

Code: Alles auswählen

class Planet():
    def __repr__(self):
        class_name = type(self).__name__
        x, y = self.position
        return '{}(x={}, y={})'.format(class_name, x, y)
jetzt wird mir immer der __name__ von allen Planet-instanzen auf "instance" gesetzt
die ausgabe von planetinstance.__repr__() ist dann "instance{x=..., y=...}".
wie kann das passiert sein?
__repr__ hast du ja selbst definiert und vorgegeben, was da bei return zurückkommt. Neben x und y auch class_name. Praktischerweise wird class_name genau 2 Zeilen drüber festgelegt. Wenn du dir das anschaust, welche Ausgabe würdest du erwarten, wenn nicht "instance"? Solche Fragen kann man gut im interaktiven Interpreter ausprobieren und Schritt für Schritt leichter oder komplizierter werden, bis alle Unklarheiten beseitigt sind. :wink:

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 20:14
von BlackJack
@Kebap: Also mich würde auch interessieren warum da 'instance' bei raus kommen soll:
[codebox=pycon file=Unbenannt.txt]>>> class Planet():
... def __repr__(self):
... class_name = type(self).__name__
... x, y = self.position
... return '{}(x={}, y={})'.format(class_name, x, y)
...
>>> p = Planet()
>>> p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __repr__
AttributeError: 'Planet' object has no attribute 'position'
>>> p.position = (1,2)
>>> p
Planet(x=1, y=2)
>>> type(p)
<class '__main__.Planet'>
>>> type(p).__name__
'Planet'[/code]

@Pygoscelis papua: Konvention für `__repr__()` ist das da entweder etwas raus kommt das man im Quelltext so schreiben könnte um ein gleiches Objekt zu erhalten, oder das die `repr()`-Darstellung in spitze Klammern eingefasst wird. Beispielsweise '<Planet x=… y=…>'.

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 21:28
von snafu
Der Sinn, warum man den Namen dynamisch über das __name__ Attribut des Typen ermittelt anstatt ihn einfach direkt hinzuschreiben, ist übrigens der Gedanke an Vererbung. Wenn jetzt jemand einen RedPlanet ableiten würde, dann zeigt __repr__() einem automatisch RedPlanet(...) an, ohne dass man die Methode anpassen müsste. Ausgenommen sind natürlich Fälle, wo neue Attribute eingeführt werden. Die werden dann nicht automatisch angezeigt. Wenn man das auf die Spitze treiben möchte, dann ginge auch so etwas:

Code: Alles auswählen

class Planet(object):
    def __init__(self, position, size):
        self.position = position
        self.size = size
        self._repr_names = ['position', 'size']

    def __repr__(self):
        class_name = type(self).__name__
        signature = ', '.join(
            '{}={!r}'.format(name, getattr(self, name))
            for name in self._repr_names
        )
        return '{}({})'.format(class_name, signature)


class ColoredPlanet(Planet):
    def __init__(self, position, size, color):
        Planet.__init__(self, position, size)
        self.color = color
        self._repr_names.append('color')


def main():
    planet = Planet((23, 42), 2342)
    red_planet = ColoredPlanet((23, 42), 2342, 'red')
    print(planet)
    print(red_planet)

if __name__ == '__main__':
    main()
Aber das nur nebenbei. Gibt ja bereits nametuple(), sodass man diese Dinge eigentlich nicht nochmal neu erfinden muss. In echtem Code würde ich das wahrscheinlich als Mixin implementieren, wenn nametuple() mir aus irgendwelchen Gründen nicht geeignet erscheint.

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 21:51
von Pygoscelis papua
die Ausgabe instance ist aber nicht nur bei __repr__() sondern auch bei
type(Planet).__name__ bzw. wenn ich schreibe Planer(parameter).name
Woran kann das denn liegen? Ich kapier es einfach nicht.
Und die __repr__() funktion hat snafu geschrieben nicht ich :)
@kepab ich hätte dort die ausgabe "Planet" erwartet wie bei allen anderen klassen
meine klasse heißt ja nicht instance.
hier mal dazu eine Ausgabe aus meinem Interpreter:

Code: Alles auswählen

[GCC 4.9.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class House():
...     pass
... 
>>> House.__name__
'House'
>>> 

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 22:00
von snafu
Da stand nicht type(Planet).__name__, sondern type(self).__name__

Und niemand zwingt dich, Code zu übernehmen, dessen Sinn dir nicht klar ist. Dann kann man auch fragen oder es weglassen.

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 22:08
von snafu
Übrigens, type(Planet()).__name__ ergibt "instance", wenn man die Klasse unter Python 2.x ohne Basisklasse definiert. Daher sollte man immer von object erben, wenn man keine andere Basisklasse hat. Sonst erhält man unter Python 2 oldstyle-Klassen.

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 22:13
von Pygoscelis papua
was ist denn da der Unterschied?
hier eine andere Ausgabe aus meinem interpreter:

Code: Alles auswählen

>>> class House:
...     def __repr__(self):
...         return type(self).__name__
... 
>>> a = House()
>>> a
House
>>> a.__repr__()
'House'
und ich verwende ja nur Python3
EDIT: ich habe gerade gesehen das meine IDE irgendwie auf Python2 umgestellt hatte, daher rührte der Fehler also :)
Da hätte ich jetzt auch noch wochen im code suchen können :D nächstes mal teste ich es auch außerhalb der IDE ...

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 22:23
von snafu
Ich kenne deine Entwicklungsumgebung nicht, aber "instance" kann bei type(self).__name__ AFAIK nur unter Python 2.x herauskommen, wenn wie gesagt eine "nackte" Klasse ohne Basisklasse definiert wird. Python 3.x verwendet immer automatisch Newstyle-Klassen, auch ohne "object". Ich schreibe es trotzdem immer hin, weil es nicht wehtut und den Code damit kompatibel zu Python 2.x hält.

EDIT:
Dann hat sich das ja aufgeklärt. Und sorry, dass ich dich gerade so angefahren habe. Ich hatte das "ist nicht von mir -- snafu hat das so gezeigt" wohl ich den falschen Hals gekriegt... ;)

Re: Klasse verschiedene varianten

Verfasst: Samstag 14. Januar 2017, 22:24
von Pygoscelis papua
ok dann mache ich das auch.