Antworten:
Dies bedeutet im Grunde, dass das Objekt die __getitem__()
Methode implementiert . Mit anderen Worten, es beschreibt Objekte, die "Container" sind, dh sie enthalten andere Objekte. Dies umfasst Zeichenfolgen, Listen, Tupel und Wörterbücher.
[
... ]
Indexierungssyntax wird als Index bezeichnet , da sie der mathematischen Notation entspricht, bei der tatsächliche Indizes verwendet werden. zB a[1]
ist Python für das, was Mathematiker als a₁ schreiben würden . "Subskriptierbar" bedeutet also "subskriptierbar". Was in Python-Begriffen bedeutet, dass es implementiert werden muss __getitem__()
, da a[1]
es sich nur um syntaktischen Zucker handelt a.__getitem__(1)
.
hasattr
sollte gut funktionieren, aber es ist nicht die pythonische Art, Dinge zu tun. Die Python-Praxis fördert das Entenschreiben . Das heißt, wenn Sie versuchen, ein Element mithilfe eines Index von Ihrem Objekt abzurufen, fahren Sie fort. Wenn Sie der Meinung sind, dass dies möglicherweise nicht funktioniert, weil das Objekt nicht tiefgestellt werden kann, schließen Sie es in einen try
Block mit einem ein except TypeError
.
Auf den ersten Blick sind die folgenden integrierten Funktionen nur abonnierbar:
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
Aber Mipadis Antwort ist richtig - jede Klasse, die implementiert, __getitem__
ist tiefstellbar
Ein skriptfähiges Objekt ist ein Objekt, das die mit ihm durchgeführten Vorgänge aufzeichnet und sie als "Skript" speichern kann, das wiedergegeben werden kann.
Beispiel: Application Scripting Framework
Wenn Alistair nicht wusste, was er fragte und wirklich "abonnierbare" Objekte meinte (wie von anderen bearbeitet), dann ist dies (wie auch Mipadi antwortete) das richtige:
Ein tiefstellbares Objekt ist jedes Objekt, das die __getitem__
spezielle Methode implementiert (Denklisten, Wörterbücher).
Die Bedeutung des Index beim Rechnen ist: "Ein Symbol (fiktiv als Index geschrieben, in der Praxis jedoch normalerweise nicht), das in einem Programm allein oder mit anderen verwendet wird, um eines der Elemente eines Arrays anzugeben."
Nun zu dem einfachen Beispiel von @ user2194711 wir nun sehen, dass das anhängende Element aus zwei Gründen nicht Teil der Liste sein kann:
1) Wir rufen die Methode append nicht wirklich auf; weil es braucht()
es nennen muss.
2) Der Fehler zeigt an, dass die Funktion oder Methode nicht tiefgestellt werden kann. bedeutet, dass sie nicht wie eine Liste oder Sequenz indizierbar sind.
Nun sehen Sie dies: -
>>> 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
Das heißt, es gibt keine Indizes oder sagen Elemente, function
wie sie in Sequenzen vorkommen. und wir können nicht wie wir mit Hilfe von auf sie zugreifen[]
.
Ebenfalls; wie Mipadi in seiner Antwort sagte; Dies bedeutet im Grunde, dass das Objekt die __getitem__()
Methode implementiert . (wenn es abonnierbar ist). So entstand der Fehler:
arr.append["HI"]
TypeError: Das Objekt 'builtin_function_or_method' kann nicht tiefgestellt werden
Ich hatte das gleiche Problem. ich habe getan
arr = []
arr.append["HI"]
Die Verwendung [
verursachte also einen Fehler. Es sollte seinarr.append("HI")
Als Folge der früheren Antworten hier ist dies sehr oft ein Zeichen dafür, dass Sie glauben, eine Liste (oder ein Diktat oder ein anderes abonnierbares Objekt) zu haben, wenn Sie dies nicht tun.
Zum Beispiel, sagen wir , Sie haben eine Funktion , die sollte eine Liste zurückkehren;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
Was passiert nun, wenn Sie diese Funktion aufrufen und something_happens()
aus irgendeinem Grund keinen True
Wert zurückgeben? Das if
scheitert, und so fallen Sie durch; gimme_things
macht nicht explizit return
etwas - also wird es tatsächlich implizit return None
. Dann dieser Code:
things = gimme_things()
print("My first thing is {0}".format(things[0]))
wird mit " NoneType
Objekt ist nicht abonnierbar" fehlschlagen, weil, na ja , things
ist None
und Sie versuchen, dies zu tun, None[0]
was keinen Sinn ergibt, weil ... was die Fehlermeldung sagt.
Es gibt zwei Möglichkeiten, diesen Fehler in Ihrem Code zu beheben: Die erste besteht darin, den Fehler zu vermeiden, indem Sie überprüfen, ob er things
tatsächlich gültig ist, bevor Sie versuchen, ihn zu verwenden.
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 ...
oder äquivalent die TypeError
Ausnahme abfangen;
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 ...
Eine andere Möglichkeit besteht darin, das Design gimme_things
so zu gestalten , dass sichergestellt ist, dass immer eine Liste zurückgegeben wird. In diesem Fall ist dies wahrscheinlich das einfachere Design, da es bedeutet, dass es viele Orte gibt, an denen Sie einen ähnlichen Fehler haben, diese einfach und idiomatisch gehalten werden können.
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 []
Was Sie in die else:
Branche einfügen, hängt natürlich von Ihrem Anwendungsfall ab. Vielleicht sollten Sie eine Ausnahme something_happens()
auslösen, wenn dies fehlschlägt, um klarer und deutlicher zu machen, wo tatsächlich etwas schief gelaufen ist? Das Hinzufügen von Ausnahmen zu Ihrem eigenen Code ist eine wichtige Möglichkeit, um genau zu erfahren, was passiert, wenn etwas fehlschlägt!
(Beachten Sie auch , wie diese letztere fix immer noch nicht vollständig um den Fehler zu beheben - es verhindert , dass Sie zu Index versucht , None
aber things[0]
eine immer noch , IndexError
wenn things
eine leere Liste ist , wenn Sie eine haben. try
Sie tun können , except (TypeError, IndexError)
zu stoppen es auch.)
hasattr(SomeClassWithoutGetItem, '__getitem__')
festzustellen, ob eine Sache abonnierbar ist?