web-dev-qa-db-fra.com

qu'est-ce que cela signifie si un objet est souscrit ou non?

Quels types d'objets tombent dans le domaine "enregistrable"?

301
Alistair

Cela signifie fondamentalement que l'objet implémente la méthode __getitem__(). En d'autres termes, il décrit des objets qui sont des "conteneurs", c'est-à-dire qu'ils contiennent d'autres objets. Cela inclut les listes, les tuples et les dictionnaires.

276
mipadi

Voici les seuls éléments intégrés pouvant être indexés:

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

Mais la réponse de mipadi est correcte - toute classe implémentant __getitem__ est subscriptable

65
Dan

Un objet scriptable est un objet qui enregistre les opérations effectuées et peut les stocker sous la forme d'un "script" pouvant être rejoué.

Par exemple, voir: Application Scripting Framework

Maintenant, si Alistair ne savait pas ce qu’il demandait et voulait vraiment dire des objets "subscriptables" (édités par d’autres), alors (comme mipadi a également répondu) c’est le bon:

Un objet pouvant être souscrit est tout objet qui implémente la méthode spéciale __getitem__ (listes de réflexion, dictionnaires).

15
tzot

La signification de l'indice en informatique est: "un symbole (écrit théoriquement sous la forme d'un indice mais généralement pas utilisé) utilisé dans un programme, seul ou associé à d'autres, pour spécifier l'un des éléments d'un tableau."

Maintenant, dans l’exemple simple donné par @ user2194711 , nous pouvons voir que l’élément ajouté ne peut pas faire partie de la liste pour deux raisons: -

1) Nous n'appelons pas vraiment la méthode append; parce qu'il a besoin de () pour l'appeler.

2) l'erreur indique que la fonction ou la méthode n'est pas enregistrable; signifie qu'ils ne sont pas indexables comme une liste ou une séquence.

Maintenant, voyez ceci: -

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

Cela signifie qu’il n’ya pas d’indices ni d’éléments dits dans function comme ils apparaissent dans les séquences; et nous ne pouvons pas y accéder comme nous le faisons, avec l'aide de [].

Aussi; comme mipadi dit dans sa réponse; Cela signifie fondamentalement que l'objet implémente la méthode __getitem__(). (s'il est enregistrable). Ainsi l'erreur a produit:

arr.append["HI"]

TypeError: l'objet 'builtin_function_or_method' n'est pas souscriptable

12
Vicrobot

J'ai eu le même problème. je faisais

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

Donc, utiliser [ causait une erreur. Ce devrait être arr.append("HI")

7
user2194711

En corollaire aux réponses précédentes, il s'agit très souvent d'un signe indiquant que vous pensez avoir une liste (ou un dict, ou un autre objet pouvant être soumis à une souscription), alors que ce n'est pas le cas.

Par exemple, supposons que vous ayez une fonction qui devrait renvoie une liste;

def gimme_things():
    if something_happens():
        return ['all', 'the', 'things']

Maintenant, lorsque vous appelez cette fonction et que something_happens(), pour une raison quelconque, ne renvoie pas de valeur True, que se passe-t-il? La if échoue et vous échouez. gimme_things n'a pas explicitement return rien - alors en fait, il implicitement return None. Alors ce code:

things = gimme_things()
print("My first thing is {0}".format(things[0]))

échouera avec "NoneType l'objet n'est pas souscriptable" car, bien, things est None et vous essayez donc de faire None[0] ce qui n'a pas de sens, car .. Qu'est-ce que le message d'erreur dit?.

Il existe deux manières de corriger ce bogue dans votre code - la première consiste à éviter l'erreur en vérifiant que things est en fait valide avant de tenter de l'utiliser;

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 emprisonne de manière équivalente l'exception TypeError;

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

Une autre solution consiste à repenser gimme_things afin de vous assurer qu'il renvoie toujours une liste. Dans ce cas, c'est probablement la conception la plus simple car cela signifie que s'il existe de nombreux endroits où vous avez un bogue similaire, ils peuvent rester simples et idiomatiques.

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 []

Bien entendu, ce que vous mettez dans la branche else: dépend de votre cas d'utilisation. Peut-être devriez-vous lever une exception lorsque something_happens() échoue, pour rendre plus évident et explicite les cas où quelque chose s'est mal passé? Ajouter des exceptions à votre propre code est un moyen important de savoir exactement ce qui se passe lorsque quelque chose ne fonctionne pas!

(Notez également que ce dernier correctif ne résout toujours pas complètement le bogue - il vous empêche d'essayer de sous-indiquer None mais things[0] est toujours un IndexError lorsque things est une liste vide. Si vous avez une try, vous pouvez aussi utiliser except (TypeError, IndexError) pour la capturer également.)

1
tripleee