Risposte:
Fondamentalmente significa che l'oggetto implementa il __getitem__()
metodo. In altre parole, descrive oggetti che sono "contenitori", nel senso che contengono altri oggetti. Ciò include stringhe, elenchi, tuple e dizionari.
[
... ]
indicizzazione è chiamata pedice , poiché equivale alla notazione matematica che utilizza pedici effettivi; ad esempio a[1]
Python è ciò che i matematici scriverebbero come a₁ . Quindi "sottoscrivibile" significa "in grado di essere sottoscritto". Il che, in termini di Python, significa che deve essere implementato __getitem__()
, poiché a[1]
è solo zucchero sintattico per a.__getitem__(1)
.
hasattr
dovrebbe funzionare bene, ma non è il modo Pythonic di fare le cose; La pratica di Python incoraggia Duck Typing . Vale a dire, se hai intenzione di provare a recuperare un oggetto dal tuo oggetto usando un pedice, vai avanti e fallo; se pensi che potrebbe non funzionare perché l'oggetto non è sottoscrivibile, avvolgilo in un try
blocco con un except TypeError
.
Al di sopra della mia testa, i seguenti sono gli unici incorporati che sono abbonabili:
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
Ma la risposta di mipadi è corretta: qualsiasi classe implementata __getitem__
è iscrivibile
Un oggetto con script è un oggetto che registra le operazioni eseguite e può memorizzarle come "script" che possono essere riprodotti.
Ad esempio, vedere: Application Scripting Framework
Ora, se Alistair non sapeva cosa chiedeva e intendeva davvero oggetti "sottoscrivibili" (come modificato da altri), allora (come anche Mipadi ha risposto) questo è quello corretto:
Un oggetto sottoscrivibile è qualsiasi oggetto che implementa il __getitem__
metodo speciale (elenchi di pensiero, dizionari).
Il significato di pedice nell'informatica è: "un simbolo (teoricamente scritto come pedice ma in pratica di solito no) utilizzato in un programma, da solo o con altri, per specificare uno degli elementi di un array".
Ora, nel semplice esempio fornito da @ user2194711 , possiamo vedere che l'elemento aggiunto non è in grado di far parte dell'elenco per due motivi: -
1) Non stiamo davvero chiamando il metodo append; perché deve ()
chiamarlo.
2) L'errore indica che la funzione o il metodo non è sottoscrivibile; significa che non sono indicizzabili come un elenco o una sequenza.
Ora vedi questo: -
>>> 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
Ciò significa che non ci sono pedici o elementi dire function
come si verificano nelle sequenze; e non possiamo accedervi come facciamo noi con l'aiuto di []
.
Anche; come diceva mipadi nella sua risposta; Fondamentalmente significa che l'oggetto implementa il __getitem__()
metodo. (se è abbonabile). Quindi l'errore ha prodotto:
arr.append["HI"]
TypeError: l'oggetto 'builtin_function_or_method' non è sottoscrivibile
Ho avuto lo stesso problema. stavo facendo
arr = []
arr.append["HI"]
Quindi l'utilizzo [
stava causando errori. Dovrebbe esserearr.append("HI")
Come corollario delle risposte precedenti qui, molto spesso questo è un segno che pensi di avere un elenco (o dict, o altro oggetto sottoscrivibile) quando non lo fai.
Ad esempio, supponiamo che tu abbia una funzione che dovrebbe restituire un elenco;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
Ora quando chiamate quella funzione e something_happens()
per qualche motivo non restituisce un True
valore, cosa succede? I if
fallimenti, e così cadi; gimme_things
non esplicitamente return
nulla - quindi, in effetti, lo farà implicitamente return None
. Quindi questo codice:
things = gimme_things()
print("My first thing is {0}".format(things[0]))
fallirà con "L' NoneType
oggetto non è sottoscrivibile" perché, beh, lo things
è None
e quindi stai cercando di fare ciò None[0]
che non ha senso perché ... cosa dice il messaggio di errore.
Esistono due modi per correggere questo errore nel codice: il primo è quello di evitare l'errore controllando che things
sia effettivamente valido prima di tentare di 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 intrappolare equivalentemente l' TypeError
eccezione;
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 ...
Un altro è riprogettare in gimme_things
modo da assicurarsi che restituisca sempre un elenco. In questo caso, questo è probabilmente il design più semplice perché significa che se ci sono molti posti in cui hai un bug simile, possono essere mantenuti semplici e idiomatici.
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 []
Naturalmente, ciò che metti nel else:
ramo dipende dal tuo caso d'uso. Forse dovresti sollevare un'eccezione quando something_happens()
fallisce, per rendere più ovvio ed esplicito dove qualcosa è andato storto? Aggiungere eccezioni al tuo codice è un modo importante per farti sapere esattamente cosa succede quando qualcosa non riesce!
(Nota anche come quest'ultima correzione non risolva ancora completamente il bug: ti impedisce di tentare di iscriverti, None
ma things[0]
è ancora un IndexError
quando things
è un elenco vuoto. Se ne hai uno try
puoi fare anche except (TypeError, IndexError)
per intrappolarlo.)
hasattr(SomeClassWithoutGetItem, '__getitem__')
determinare se una cosa è iscrivibile?