¿Qué significa si un objeto Python es "subscriptable" o no?
¿Qué tipos de objetos caen en el dominio de "suscriptibles"?
Básicamente significa que el objeto implementa el __getitem__()
método. En otras palabras, describe objetos que son "contenedores", es decir, que contienen otros objetos. Esto incluye cadenas, listas, tuplas y diccionarios.
En lo que se me ocurre, las siguientes son las únicas funciones integradas que se pueden subscribir:
string: "foobar"[3] == "b"
tuple: (1,2,3,4)[3] == 4
list: [1,2,3,4][3] == 4
dict: {"a":1, "b":2, "c":3}["c"] == 3
Pero la respuesta de mipadi es correcta: cualquier clase que implemente __getitem__
tiene subíndices
El significado de subíndice en informática es: "un símbolo (teóricamente escrito como subíndice pero en la práctica generalmente no) utilizado en un programa, solo o con otros, para especificar uno de los elementos de una matriz".
Ahora, en el ejemplo simple dado por @ user2194711 podemos ver que el elemento agregado no puede ser parte de la lista por dos razones:
Realmente no estamos llamando al método append; porque necesita
()
llamarlo.El error indica que la función o método no se puede subscribir; significa que no son indexables como una lista o secuencia.
Ahora mira esto: -
>>> var = "myString"
>>> def foo(): return 0
...
>>> var[3]
't'
>>> foo[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable
Eso significa que no hay subíndices ni elementos similares a function
los que aparecen en secuencias; y no podemos acceder a ellos como lo hacemos habitualmente, con la ayuda de []
.
También; como dijo mipadi en su respuesta; Básicamente significa que el objeto implementa el __getitem__()
método. (si es subscriptible). Así el error produjo:
arr.append["HI"]
TypeError: el objeto 'builtin_function_or_method' no tiene subíndices
si es "programable"
Un objeto programable es un objeto que registra las operaciones que se le realizan y puede almacenarlas como un "script" que se puede reproducir.
Por ejemplo, consulte: Marco de secuencias de comandos de aplicaciones
si es “suscriptible”
Ahora, si Alistair no sabía lo que preguntó y realmente quiso decir objetos "subscriptibles" (según lo editado por otros), entonces (como también respondió mipadi) este es el correcto:
Un objeto subscriptible es cualquier objeto que implemente el __getitem__
método especial (listas de ideas, diccionarios).
Tuve el mismo problema. estaba haciendo
arr = []
arr.append["HI"]
Entonces el uso [
estaba causando un error. Debería serarr.append("HI")
Como corolario de las respuestas anteriores aquí, muy a menudo esto es una señal de que cree que tiene una lista (o dict u otro objeto subscriptable) cuando no la tiene.
Por ejemplo, digamos que tiene una función que debería devolver una lista;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
Ahora cuando llamas a esa función y something_happens()
por alguna razón no devuelve un True
valor, ¿qué sucede? El if
falla, y por eso fracasas; gimme_things
no hace return
nada explícitamente, por lo que, de hecho, lo hará implícitamente return None
. Entonces este código:
things = gimme_things()
print("My first thing is {0}".format(things[0]))
fallará con " NoneType
el objeto no es subscriptable" porque, bueno, things
lo es None
y por eso estás intentando hacer None[0]
lo cual no tiene sentido porque... lo que dice el mensaje de error.
Hay dos formas de corregir este error en su código: la primera es evitar el error verificando que things
sea válido antes de intentar usarlo;
things = gimme_things()
if things:
print("My first thing is {0}".format(things[0]))
else:
print("No things") # or raise an error, or do nothing, or ...
o de manera equivalente atrapar la TypeError
excepción;
things = gimme_things()
try:
print("My first thing is {0}".format(things[0]))
except TypeError:
print("No things") # or raise an error, or do nothing, or ...
Otra es rediseñar gimme_things
para asegurarse de que siempre devuelva una lista. En este caso, ese es probablemente el diseño más simple porque significa que si hay muchos lugares donde tienes un error similar, se pueden mantener simples e idiomáticos.
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
else: # make sure we always return a list, no matter what!
logging.info("Something didn't happen; return empty list")
return []
Por supuesto, lo que pongas en la else:
rama depende de tu caso de uso. ¿Quizás debería plantear una excepción cuando something_happens()
falla, para que sea más obvio y explícito dónde algo salió mal? ¡Agregar excepciones a su propio código es una forma importante de saber exactamente qué sucede cuando algo falla!
(Observe también cómo esta última solución aún no soluciona completamente el error: le impide intentar crear un subíndice, None
pero things[0]
sigue IndexError
siendo things
una lista vacía. Si tiene una , también try
puede hacerlo except (TypeError, IndexError)
para detectarla).