Ключевое слово Python "in" вызывает KeyError - PullRequest
1 голос
/ 27 октября 2019

Чтобы проверить наличие ключа в классе TodoistAPI, я использую ключевое слово "in". Тем не менее, это вызывает KeyError.

Я выделил фрагменты кода, чтобы проверить, что именно вызывает KeyError и какие входные данные предоставляются.

api = TodoistAPI(token)
api.sync()
print("id" in api.state["items"][0])

api.state["items"][0] содержит:

Item({'assigned_by_uid': None,
 'checked': 0,
 'child_order': 0,
 'collapsed': 0,
 'content': 'example task',
 'date_added': '0',
 'date_completed': None,
 'day_order': 0,
 'due': {'date': '0',
         'is_recurring': True,
         'lang': 'de',
         'string': 'every day',
         'timezone': None},
 'has_more_notes': False,
 'id': 0,
 'in_history': 0,
 'is_deleted': 0,
 'labels': [0, 0],
 'parent_id': None,
 'priority': 1,
 'project_id': 0,
 'responsible_uid': None,
 'section_id': None,
 'sync_id': None,
 'user_id': 0})

Я ожидаю, что вывод print(...) будет True или False, но фактический вывод будет следующим:

Traceback (most recent call last):
File "/Users/path/to/file.py", line 11, in 
print("id" in applicationInterface.state["items"][0])
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/todoist/models.py", line 16, in __getitem__
return self.data[key]
KeyError: 0

Process finished with exit code 1

Я также создал проблему в TodoistGithub-репозиторий: https://github.com/Doist/todoist-python/issues/64

1 Ответ

1 голос
/ 27 октября 2019

В конечном счете, это ошибка в библиотеке Todoist.

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

item = api.state["items"][0]
print("id" in item)

Это означает, что когда вы пишете "id" in item, Python проверяет метод __contains__ в классе. Item класс не определяет __contains__, но определяет __getitem__ (через его базу Model).

В соответствии со ссылкой на язык Python __getitem__ будет называться для оценки in, используя откат к протоколу последовательности .

Я думаю, что логика, используемая для оценки "id" in item, эквивалентна этому:

## Implicit logic used to evaluate `"id" in item`
for i in itertools.count():
    try:
        result = item[i]
    except IndexError:
        return False

    if result is "id" or result == "id":
        return True
return False

В пределах оценки Model.__getitem__ возникает KeyError. На фундаментальном уровне, если Model является типом отображения, я думаю, что он должен реализовывать __contains__, а также __getitem__. Модель данных Python гласит:

Рекомендуется, чтобы как отображения, так и последовательности реализовывали метод __contains__(), чтобы обеспечить эффективное использование оператора in;для сопоставлений in должен искать ключи сопоставления

...