Respuestas:
Básicamente significa que el objeto implementa el __getitem__()
método. En otras palabras, describe objetos que son "contenedores", lo que significa que contienen otros objetos. Esto incluye cadenas, listas, tuplas y diccionarios.
[
... ]
sintaxis de la indexación se llama un subíndice , porque es equivalente a la notación matemática que utiliza subíndices reales; Por ejemplo, a[1]
Python es lo que los matemáticos escribirían como a₁ . Entonces "subscriptable" significa "capaz de ser subcripted". Lo cual, en términos de Python, significa que tiene que implementarse __getitem__()
, ya que a[1]
es solo azúcar sintáctico para a.__getitem__(1)
.
hasattr
debería funcionar bien, pero no es la forma pitónica de hacer las cosas; La práctica de Python anima a Duck Typing . Es decir, si planea intentar obtener un elemento de su objeto utilizando un subíndice, continúe y hágalo; Si cree que podría no funcionar porque el objeto no es subcriptable, envuélvalo en un try
bloque con un except TypeError
.
Fuera de mi cabeza, las siguientes son las únicas incorporadas que son subscriptables:
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__
es subscriptable
Un objeto programable es un objeto que registra las operaciones que se le realizan y puede almacenarlos como un "script" que puede reproducirse.
Por ejemplo, consulte: Marco de secuencias de comandos de aplicaciones
Ahora, si Alistair no sabía lo que preguntaba y realmente quería decir objetos "subscriptables" (tal como lo editaron otros), entonces (como también respondió mipadi) este es el correcto:
Un objeto subscriptable es cualquier objeto que implementa el __getitem__
método especial (listas de reflexión, diccionarios).
El significado del subíndice en informática es: "un símbolo (escrito nocionalmente como subíndice pero en la práctica generalmente no) usado 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 adjunto no puede ser parte de la lista debido a 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 es subscriptable; 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 o dicen elementos function
como si ocurrieran en secuencias; y no podemos acceder a ellos como lo hacemos, 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 subscriptable). Así el error producido:
arr.append["HI"]
TypeError: el objeto 'builtin_function_or_method' no es subscriptable
Tuve el mismo problema. estaba haciendo
arr = []
arr.append["HI"]
Entonces usar [
estaba causando un error. Debería serarr.append("HI")
Como corolario de las respuestas anteriores aquí, muy a menudo es una señal de que crees que tienes una lista (o dict, u otro objeto suscriptable) cuando no la tienes.
Por ejemplo, supongamos que tiene una función que debería devolver una lista;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
Ahora, cuando llama a esa función, y something_happens()
por alguna razón no devuelve un True
valor, ¿qué sucede? El if
falla, y entonces caes; gimme_things
no hace nada explícitamente return
, entonces, 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 "el NoneType
objeto no es subscriptible" porque, bueno, sí lo things
está None
y está intentando hacerloNone[0]
lo que 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 comprobando 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 equivalentemente 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 tiene un error similar, pueden mantenerse 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 pones 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 hacerse saber exactamente qué sucede cuando algo falla!
(Observe también cómo esta última solución todavía no soluciona completamente el error: evita que intente subíndice None
pero things[0]
sigue siendo un IndexError
cuándo things
es una lista vacía. Si tiene una try
, puede hacer except (TypeError, IndexError)
para atraparla también).
hasattr(SomeClassWithoutGetItem, '__getitem__')
determinar si una cosa es subcriptable?