Respostas:
Basicamente, significa que o objeto implementa o __getitem__()
método. Em outras palavras, descreve objetos que são "contêineres", o que significa que eles contêm outros objetos. Isso inclui strings, listas, tuplas e dicionários.
[
... ]
sintaxe de indexação é chamada de subscrito , porque é equivalente a notação matemática que usa subscritos reais; por exemplo, a[1]
é Python para o que os matemáticos escreveriam como a₁ . Portanto, "subscrito" significa "capaz de ser inscrito". O que, em termos do Python, significa que ele precisa ser implementado __getitem__()
, já que a[1]
é apenas o açúcar sintático a.__getitem__(1)
.
hasattr
deve funcionar bem, mas não é a maneira pitônica de fazer as coisas; A prática de Python incentiva a digitação de pato . Ou seja, se você planeja tentar buscar um item do seu objeto usando um índice, vá em frente e faça-o; se você acha que pode não funcionar porque o objeto não é subscrito, envolva-o em um try
bloco com um except TypeError
.
Em cima da minha cabeça, a seguir estão os únicos built-ins que podem ser subscritos:
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
Mas a resposta de mipadi está correta - qualquer classe que implementa __getitem__
é subscrita
Um objeto com script é um objeto que registra as operações realizadas e pode armazená-las como um "script" que pode ser reproduzido.
Por exemplo, consulte: Application Scripting Framework
Agora, se Alistair não sabia o que ele pedia e realmente significava objetos "subscritíveis" (como editados por outros), então (como mipadi também respondeu), este é o correto:
Um objeto subscrito é qualquer objeto que implementa o __getitem__
método especial (listas de reflexão, dicionários).
O significado de subscrito na computação é: "um símbolo (escrito como um subscrito, mas na prática geralmente não) usado em um programa, sozinho ou com outros, para especificar um dos elementos de uma matriz".
Agora, no exemplo simples dado por @ user2194711 , podemos ver que o elemento anexado não pode fazer parte da lista por dois motivos: -
1) Não estamos realmente chamando o método append; porque precisa ()
chamá-lo.
2) O erro está indicando que a função ou método não é subscrito; significa que eles não são indexáveis como uma lista ou sequência.
Agora veja o seguinte: -
>>> 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
Isso significa que não há subscritos ou elementos digamos function
como eles ocorrem em sequências; e não podemos acessá-los como fazemos, com a ajuda de []
.
Além disso; como mipadi disse em sua resposta; Basicamente, significa que o objeto implementa o __getitem__()
método. (se for subscrito). Assim, o erro produzido:
arr.append["HI"]
TypeError: o objeto 'builtin_function_or_method' não é subscrito
Eu tive esse mesmo problema. eu estava fazendo
arr = []
arr.append["HI"]
Então, o uso [
estava causando erro. Deveria serarr.append("HI")
Como corolário das respostas anteriores aqui, muitas vezes isso é um sinal de que você acha que tem uma lista (ou ditado ou outro objeto subscrito) quando não o tem.
Por exemplo, digamos que você tenha uma função que deve retornar uma lista;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
Agora, quando você chama essa função e, something_happens()
por algum motivo, não retorna um True
valor, o que acontece? O if
fracasso, e então você cai; gimme_things
não explicitamente return
nada - então, de fato, implicitamente return None
. Então este código:
things = gimme_things()
print("My first thing is {0}".format(things[0]))
falhará com " NoneType
objeto não é subscrito" porque, bem, things
é None
e você está tentando fazer o None[0]
que não faz sentido, porque ... o que a mensagem de erro diz.
Há duas maneiras de corrigir esse bug no seu código - a primeira é evitar o erro, verificando se things
é realmente válido antes de tentar usá-lo;
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 ...
ou equivalentemente interceptar a TypeError
exceção;
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 ...
Outra é redesenhar gimme_things
para que você sempre retorne uma lista. Nesse caso, esse é provavelmente o design mais simples, porque significa que, se houver muitos lugares onde você tem um bug semelhante, eles podem ser mantidos 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 []
Obviamente, o que você coloca na else:
ramificação depende do seu caso de uso. Talvez você deva criar uma exceção quando something_happens()
falhar, para torná-la mais óbvia e explícita onde algo realmente deu errado? Adicionar exceções ao seu próprio código é uma maneira importante de informar exatamente o que acontece quando algo falha!
(Observe também como essa última correção ainda não corrige completamente o erro - ela impede que você tente se inscrever, None
mas things[0]
ainda é uma lista vazia IndexError
quando things
está vazia. Se você tiver uma, try
poderá fazer except (TypeError, IndexError)
uma interceptação também.)
hasattr(SomeClassWithoutGetItem, '__getitem__')
determinar se algo é subscrito?