Cosa significa se un oggetto Python è "sottoscrivibile" o no?


Risposte:


357

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.


2
Quanto sarebbe affidabile: hasattr(SomeClassWithoutGetItem, '__getitem__')determinare se una cosa è iscrivibile?
jmunsch,

2
La sintassi di [... ]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).
Mark Reed,

Quella chiamata a hasattrdovrebbe 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 tryblocco con un except TypeError.
Mark Reed,

77

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


17

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


2
Nota che sto rispondendo alla domanda originale sugli oggetti "scrivibili", non "sottoscrivibili" come modificati da altri, non da Alistair. Vorrei davvero che Alistair commentasse.
tzot

Ah, un nuovo badge per la mia collezione! :) Sto scherzando, ovviamente. L'unica cosa che giustificava la modifica della domanda era che Alistair sceglieva una risposta; Non sono ancora sicuro che Alistair fosse sicuro di scegliere.
martedì

17

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 functioncome 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


7

Ho avuto lo stesso problema. stavo facendo

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

Quindi l'utilizzo [stava causando errori. Dovrebbe esserearr.append("HI")


3

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 Truevalore, cosa succede? I iffallimenti, e così cadi; gimme_thingsnon esplicitamente returnnulla - 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' NoneTypeoggetto non è sottoscrivibile" perché, beh, lo thingsè Nonee 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 thingssia 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' TypeErroreccezione;

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_thingsmodo 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, Nonema things[0]è ancora un IndexErrorquando thingsè un elenco vuoto. Se ne hai uno trypuoi fare anche except (TypeError, IndexError)per intrappolarlo.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.