Revisé la mayor parte de la documentación de __getitem__ en los documentos de Python, pero aún no puedo comprender su significado.
Entonces, todo lo que puedo entender es que __getitem__ se usa para implementar llamadas como self[key] . Pero ¿cuál es el uso de la misma?
Digamos que tengo una clase de python definida de esta manera:
class Person: def __init__(self,name,age): self.name = name self.age = age def __getitem__(self,key): print ("Inside `__getitem__` method!") return getattr(self,key) p = Person("Subhayan",32) print (p["age"]) Esto devuelve los resultados como se esperaba. Pero, ¿por qué usar __getitem__ en primer lugar? También escuché que Python llama a __getitem__ internamente. Pero ¿por qué lo hace?
¿Puede alguien explicar esto con más detalle?
Cong Ma hace un buen trabajo al explicar para qué se usa __getitem__ , pero quiero darte un ejemplo que podría ser útil. Imagina una clase que modela un edificio. Dentro de los datos del edificio incluye una serie de atributos, incluyendo descripciones de las empresas que ocupan cada piso:
Sin usar __getitem__ tendríamos una clase como esta:
class Building(object): def __init__(self, floors): self._floors = [None]*floors def occupy(self, floor_number, data): self._floors[floor_number] = data def get_floor_data(self, floor_number): return self._floors[floor_number] building1 = Building(4) # Construct a building with 4 floors building1.occupy(0, 'Reception') building1.occupy(1, 'ABC Corp') building1.occupy(2, 'DEF Inc') print( building1.get_floor_data(2) ) Sin embargo, podríamos usar __getitem__ (y su contraparte __setitem__ ) para hacer que el uso de la clase Building sea 'más agradable'.
class Building(object): def __init__(self, floors): self._floors = [None]*floors def __setitem__(self, floor_number, data): self._floors[floor_number] = data def __getitem__(self, floor_number): return self._floors[floor_number] building1 = Building(4) # Construct a building with 4 floors building1[0] = 'Reception' building1[1] = 'ABC Corp' building1[2] = 'DEF Inc' print( building1[2] ) El hecho de que use __setitem__ como este realmente depende de cómo planee abstraer sus datos; en este caso, hemos decidido tratar un edificio como un contenedor de pisos (y también podría implementar un iterador para el Edificio, y tal vez incluso la capacidad de rebanada, es decir, obtenga más de los datos de un piso a la vez, depende de lo que necesite.
La sintaxis [] para obtener un elemento por clave o índice es solo azúcar de sintaxis.
Cuando evalúa a[i] Python llama a.__getitem__(i) (o type(a).__getitem__(a, i) , pero esta distinción se trata de modelos de herencia y no es importante aquí). Incluso si la clase de a no define explícitamente este método, generalmente se hereda de una clase antepasada.
Todos los nombres de métodos especiales (Python 2.7) y su semántica se enumeran aquí: https://docs.python.org/2.7/reference/datamodel.html#special-method-names
El método mágico __getitem__ se usa básicamente para acceder a elementos de lista, entradas de diccionario, elementos de matriz, etc. Es muy útil para una búsqueda rápida de atributos de instancia.
Aquí estoy mostrando esto con una clase de ejemplo Persona que puede ser instanciada por 'nombre', 'edad' y 'fecha de nacimiento' (fecha de nacimiento). El método __getitem__ está escrito de manera que se puede acceder a los atributos de la instancia indexada, como el nombre o apellido, el día, el mes o el año de la fecha de nacimiento, etc.
import copy # Constants that can be used to index date of birth's Date-Month-Year D = 0; M = 1; Y = -1 class Person(object): def __init__(self, name, age, dob): self.name = name self.age = age self.dob = dob def __getitem__(self, indx): print ("Calling __getitem__") p = copy.copy(self) p.name = p.name.split(" ")[indx] p.dob = p.dob[indx] # or, p.dob = p.dob.__getitem__(indx) return pSupongamos que la entrada de un usuario es la siguiente:
p = Person(name = 'Jonab Gutu', age = 20, dob=(1, 1, 1999)) Con la ayuda del método __getitem__ , el usuario puede acceder a los atributos indexados. p.ej,
print p[0].name # print first (or last) name print p[Y].dob # print (Date or Month or ) Year of the 'date of birth'