Aprende Python el ejercicio de la manera difícil 43

No comprendo cómo el script llega a la siguiente sala y, en general, cómo funcionan las clases “Motor” y “Mapa”. Aquí hay un extracto:

Class Map(object): scenes = { 'central_corridor': CentralCorridor(), 'laser_weapon_armory': LaserWeaponArmory(), 'the_bridge': TheBridge(), 'escape_pod': EscapePod(), 'death': Death() } def __init__(self, start_scene): self.start_scene = start_scene def next_scene(self, scene_name): return Map.scenes.get(scene_name) def opening_scene(self): return self.next_scene(self.start_scene) class Engine(object): def __init__(self, scene_map): self.scene_map = scene_map def play(self): current_scene = self.scene_map.opening_scene() while True: print "\n--------" next_scene_name = current_scene.enter() current_scene = self.scene_map.next_scene(next_scene_name) 

Simplemente no entiendo cómo funcionan estas porciones. Sé cómo funcionan las clases y las instancias y atributos de objetos, y todas esas otras cosas de POO, pero por alguna razón, esta parte del código no lo consigo. Principalmente la clase de mapa. Si alguien pudiera explicarlo sería genial.

También (esto puede requerir leer el ejercicio), ¿por qué es necesario tener estas dos clases de todos modos? ¿No podría simplemente hacerlo con métodos de clase (es decir, métodos sin uno mismo como parámetro)? Luego, simplemente puede llamar, por ejemplo, CentralCorridor.enter (). De hecho, así es como lo resolví antes de leer la respuesta, y funcionó bien.

Lo siento, mi pregunta principal es cómo funcionan las clases de motor y mapa. Lo otro es secundario.

¡Gracias por adelantado!

El objeto Map es una clase que mapea tus escenas. Tiene algunas escenas guardadas en una matriz.

 scenes = { 'central_corridor': CentralCorridor(), 'laser_weapon_armory': LaserWeaponArmory(), 'the_bridge': TheBridge(), 'escape_pod': EscapePod(), 'death': Death() } 

Cuando se hace un objeto de Mapa, también se le da una escena de apertura como se ve en el constructor

 def __init__(self, start_scene): self.start_scene = start_scene 

Esto crea una variable en el Map llamada start_scene contiene su escena inicial.

Además el Map tiene 2 métodos.

 # This one returns a scene based on its name or key in the scenes array def next_scene(self, scene_name): return Map.scenes.get(scene_name) # And this one returns the opening scene which is set when you create the map. def opening_scene(self): return self.next_scene(self.start_scene) 

El Engine parece estar controlando las escenas de cuándo jugar y qué jugar.

 # When creating an Engine object you give the map containing scenes to its constructor def __init__(self, scene_map): self.scene_map = scene_map # The method which starts playing the scenes def play(self): # the opening scene from the map is selected as the current scene current_scene = self.scene_map.opening_scene() # You loop all the scenes probably, conditions of this loop are unknown because you haven't posted it entirely. while True: print "\n--------" # It seems the next scene name is known in the current scene next_scene_name = current_scene.enter() # It replaces current scene with the next scene from the map current_scene = self.scene_map.next_scene(next_scene_name) 

¿Por qué es necesario tener estas dos clases de todos modos?

No lo es, a menos que sea requerido de acuerdo a su asignación.

Como dijiste, es posible hacerlo sin ti, PERO hay buenas razones para hacerlo.

De esta manera usted hace 2 clases separadas con sus propias responsabilidades. De esta manera, el código es más legible cuando la aplicación se hace más y más grande. Y es fácil navegar a través de la aplicación. Puedes cambiar partes de tu aplicación, etc., etc. Mi consejo es que sigas practicando y leyendo sobre OOP, te darás cuenta de por qué haces las cosas que ves.

La clase de mapa tiene un diccionario de nombres de escenas que son claves e instancias de diferentes clases como valores. Para recuperar una de las instancias, llama a un método que pasa una cadena que es el nombre de la escena. La clase Map luego devuelve una instancia de la clase correspondiente.

¿No podría simplemente hacerlo con métodos de clase (es decir, métodos sin uno mismo como parámetro)? Luego, simplemente puede llamar, por ejemplo, CentralCorridor.enter ().

Si, podrías. El inconveniente es que ahora tienes los nombres de tus clases de escena en tu código. Si luego decide reescribir su progtwig para eliminar algunas escenas o agregar otras, debe cambiar todos los lugares en su código donde codificó los nombres. Si emplea la clase Map, los cambios solo deben realizarse en el diccionario. Sin embargo, aún tendría que eliminar las llamadas de método que intentan recuperar instancias de clase que ha eliminado. O bien, puede hacer que el método next_scene () se ocupe de los bashs de recuperar las escenas que ha eliminado del diccionario.

Otra consideración con los métodos de clase es: ¿necesitará almacenar ‘estado’? Como, cuántos jugadores hay actualmente en la escena. Y, ¿necesitarás crear más de una escena de ese tipo?