Menu
CoddyTech

Iteradores personalizados

Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 33 de 65.

Python permite que una clase se comporte como una lista con métodos mágicos como __len__, __getitem__, __contains__ y __iter__. Godot tiene métodos virtuales para solo una de estas tareas: el bucle for. Tres métodos hacen que for item in my_object: funcione:

  • _iter_init(iter) se ejecuta una vez, antes de la primera iteración. Establece la posición inicial y devuelve true si hay un primer elemento.
  • _iter_get(position) devuelve el elemento en la posición actual, y la variable del bucle recibe ese valor.
  • _iter_next(iter) se ejecuta antes de cada iteración posterior. Avanza a la siguiente posición y devuelve false cuando no quedan más elementos, lo que finaliza el bucle.
# team.gd
class_name Team
extends RefCounted

var _members: Array[String] = []

func add(member: String) -> void:
	_members.append(member)

func _iter_init(iter: Array) -> bool:
	iter[0] = 0
	return iter[0] < _members.size()

func _iter_next(iter: Array) -> bool:
	iter[0] += 1
	return iter[0] < _members.size()

func _iter_get(position):
	return _members[position]

iter es un Array con un espacio que Godot crea para cada bucle. iter[0] contiene la posición de ese bucle, y Godot pasa su valor a _iter_get(). Ahora, un Team funciona en un bucle for:

var team := Team.new()
team.add("Ada")
team.add("Bo")
for member in team:
	print(member) # Ada, luego Bo

Mantén la posición en iter[0], no en una variable miembro como _position. Cada bucle tiene su propio iter, así que dos bucles sobre el mismo equipo, incluso uno dentro del otro, no interfieren entre sí. Con una variable miembro, el bucle interno movería la posición del bucle externo.

Las demás operaciones de lista no tienen un método virtual: len(team) y team[0] son errores. Escribe métodos ordinarios con nombres como los de Array, por ejemplo, size(), get_at(index) y has(member). No compruebes la pertenencia con in: "Ada" in team comprueba si Team tiene una propiedad o un método llamado Ada, así que es false.

challenge icon

Desafío

Fácil

Escribe la clase Bookshelf en bookshelf.gd. Guarda los títulos en _titles y admite como máximo _capacity libros:

  • add(title) añade el título y devuelve true, o devuelve false sin añadirlo cuando la estantería está llena o ya tiene ese título.
  • size() devuelve el número de libros y has(title) indica si el título está en la estantería.
  • get_at(index) devuelve el título en ese índice, o una cadena vacía cuando el índice está fuera de los límites de la estantería.
  • _iter_init(), _iter_next() y _iter_get() permiten que un bucle for recorra los títulos en el orden en que se añadieron.

El código proporcionado lee la capacidad, el número de títulos y un título por línea, e informa de los títulos que no pudo añadir. Imprime el número de libros, los enumera con un bucle for sobre la estantería, luego lee un título más e imprime si la estantería lo tiene y cuál es el último libro. Para una capacidad de 3, los títulos Dune, Emma, Dune, Ulysses, Hamlet y la búsqueda Emma, imprime:

Could not add: Dune
Could not add: Hamlet
Books: 3
1. Dune
2. Emma
3. Ulysses
Has Emma: true
Last: Ulysses

Escribe tu código en bookshelf.gd. main.gd contiene el código de entrada y salida proporcionado y no se puede editar.

Pruébalo tú mismo

extends Node

func _ready():
	# Código de entrada/salida proporcionado: mantenlo tal como está
	var shelf := Bookshelf.new(int(OS.read_string_from_stdin()))
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var title := OS.read_string_from_stdin()
		if not shelf.add(title):
			print("Could not add: " + title)
	print("Books: %d" % shelf.size())
	var number := 1
	for title in shelf:
		print("%d. %s" % [number, title])
		number += 1
	var query := OS.read_string_from_stdin()
	print("Has %s: %s" % [query, shelf.has(query)])
	print("Last: " + shelf.get_at(shelf.size() - 1))
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de GDScript online