¿Qué significa si un objeto Python es "subscriptable" o no?

Resuelto Alistair asked hace 15 años • 7 respuestas

¿Qué tipos de objetos caen en el dominio de "suscriptibles"?

Alistair avatar Oct 20 '08 04:10 Alistair
Aceptado

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.

mipadi avatar Oct 19 '2008 21:10 mipadi

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

Dan avatar Oct 19 '2008 22:10 Dan

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:

  1. Realmente no estamos llamando al método append; porque necesita ()llamarlo.

  2. 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 functionlos 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

Vicrobot avatar Mar 31 '2018 13:03 Vicrobot

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).

tzot avatar Oct 19 '2008 22:10 tzot

Tuve el mismo problema. estaba haciendo

arr = []
arr.append["HI"]

Entonces el uso [estaba causando un error. Debería serarr.append("HI")

user2194711 avatar Nov 23 '2016 13:11 user2194711

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 Truevalor, ¿qué sucede? El iffalla, y por eso fracasas; gimme_thingsno hace returnnada 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 " NoneTypeel objeto no es subscriptable" porque, bueno, thingslo es Noney 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 thingssea 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 TypeErrorexcepció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_thingspara 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, Nonepero things[0]sigue IndexErrorsiendo thingsuna lista vacía. Si tiene una , también trypuede hacerlo except (TypeError, IndexError)para detectarla).

tripleee avatar Jul 17 '2019 06:07 tripleee