Что это значит, если объект Python «подписан» или нет?

Ответы:

357

Это в основном означает, что объект реализует __getitem__()метод. Другими словами, он описывает объекты, которые являются «контейнерами», то есть они содержат другие объекты. Это включает в себя строки, списки, кортежи и словари.

mipadi
источник
2
Насколько надежным будет: hasattr(SomeClassWithoutGetItem, '__getitem__')определить, является ли вещь подписной?
Jmunsch
2
[... ]индексировать синтаксис называется индексом , потому что это равносильно математической записи , которая использует фактические индексы; Например a[1], Python для того, что математики написали бы как . Таким образом, «подписной» означает «может быть подписан». Что, в терминах Python, означает, что он должен быть реализован __getitem__(), поскольку a[1]является просто синтаксическим сахаром для a.__getitem__(1).
Марк Рид
Этот призыв hasattrдолжен работать хорошо, но это не Pythonic способ делать вещи; Практика Python поощряет Duck Typing . Это означает, что если вы планируете попытаться получить элемент из вашего объекта с помощью индекса, продолжайте и сделайте это; если вы думаете, что это может не сработать, потому что объект не может быть подписан, поместите его в tryблок с помощью except TypeError.
Марк Рид
77

Вдобавок к моей голове, следующие единственные встроенные модули, которые могут быть подписаны:

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

Но ответ Mipadi является правильным - любой класс, который реализует __getitem__является подписным

Дэн
источник
17

Объект сценариев - это объект, который записывает выполненные с ним операции и может сохранять их как «сценарий», который можно воспроизвести.

Например, см .: Application Scripting Framework

Теперь, если Алистер не знал, о чем он спрашивал, и действительно имел в виду «подписываемые» объекты (отредактированные другими), то (как ответил и Мипади) это будет правильным:

Подписываемый объект - это любой объект, который реализует __getitem__специальный метод (списки рассуждений, словари).

tzot
источник
2
Обратите внимание, что я отвечаю на первоначальный вопрос о «сценариях» объектов, а не о «подписываемых», отредактированных другими пользователями, а не Алистером. Я действительно хотел бы, чтобы Алистер прокомментировал.
tzot
Ах, новый значок для моей коллекции! :) Шучу, очевидно. Единственное, что оправдывало редактирование вопроса, было то, что Алистер выбрал ответ; Я до сих пор не уверен, что Алистер был уверен в выборе.
Цот
17

Значение индекса в вычислениях: «символ (условно записанный как индекс, но на практике обычно нет), используемый в программе, один или с другими, для указания одного из элементов массива».

Теперь в простом примере, приведенном @ user2194711 мы видим, что добавляемый элемент не может быть частью списка по двум причинам:

1) Мы не вызываем метод append; потому что это нужно ()назвать это.

2) ошибка указывает на то, что функция или метод не могут быть подписаны; означает, что они не индексируются как список или последовательность.

Теперь посмотри:

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

Это означает, что в function виде, в они встречаются в последовательностях; и мы не можем получить к ним доступ, как мы, с помощью [].

Также; как сказал Мипади в своем ответе; Это в основном означает, что объект реализует __getitem__()метод. (если это по подписке). Таким образом, ошибка выдает:

arr.append["HI"]

Ошибка типа: объект «builtin_function_or_method» не может быть подписан

Vicrobot
источник
7

У меня была такая же проблема. я делал

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

Таким образом, использование [было причиной ошибки. Должен бытьarr.append("HI")

user2194711
источник
3

Как следствие предыдущих ответов здесь, очень часто это признак того, что вы думаете, что у вас есть список (или dict, или другой подписываемый объект), когда у вас его нет.

Например, допустим, у вас есть функция, которая должна возвращать список;

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

Теперь, когда вы вызываете эту функцию и something_happens()по какой-то причине не возвращаете Trueзначение, что происходит? ifНе удается, и поэтому вы провалитесь; gimme_thingsничего явно returnне значит - так что на самом деле, это будет неявно return None. Тогда этот код:

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

потерпит неудачу с « NoneTypeобъект не подписывается», потому что, ну, thingsэто Noneи так вы пытаетесь сделатьNone[0] , что не имеет смысла , потому что ... что говорит сообщение об ошибке.

Есть два способа исправить эту ошибку в вашем коде: во-первых, чтобы избежать ошибки, проверьте, thingsдействительно ли она действительна, прежде чем пытаться ее использовать;

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

или эквивалентно заманить 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 ...

Другой - gimme_thingsизменить дизайн так, чтобы он всегда возвращал список. В этом случае, вероятно, это более простой дизайн, потому что это означает, что если во многих местах есть похожая ошибка, они могут быть простыми и идиоматичными.

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

Конечно, то, что вы положите в else:ветку, зависит от вашего варианта использования. Возможно, вам следует поднять исключение, когдаsomething_happens() неудачи, чтобы сделать его более очевидным и явным, если что-то пошло не так? Добавление исключений в ваш собственный код - это важный способ, позволяющий точно знать, что происходит, когда что-то не работает!

(Обратите также внимание на то, что это последнее исправление все еще не полностью исправляет ошибку - оно предотвращает попытки подстрочного индекса, Noneно things[0]по-прежнему является пустым списком, IndexErrorкогда thingsесть. Если у вас есть, tryвы также можете его except (TypeError, IndexError)перехватить.)

tripleee
источник