Безопасное извлечение ключа из dict () наиболее идиоматическим способом c, если ключ a.) Не существует или b.) Ключ не проверен - PullRequest
0 голосов
/ 26 февраля 2020

Итак, мне интересно. У меня есть следующая проблема, из-за которой выталкиванию словаря требуется несколько проверок и противовесов, прежде чем что-то делать с вытолкнутым значением.

Я знаю, что:

  1. Если ключ существует в словаре, то dict.pop() удаляет элемент с данным ключом из словаря и возвращает его значение.

  2. Если указанный ключ не существует в словаре, он возвращает заданное значение по умолчанию.

  3. Если данный ключ не существует в словаре, и значение pop по умолчанию не передается, то он вызывает KeyError.

Итак, я почувствовал, что 3. Мне нужно было сначала обработать исключение KeyError. Если это произойдет, извлеките этот ключ из словаря.

Затем, 2, если возвращается значение по умолчанию, никаких действий не предпринимайте.

Затем, если 1, выполните некоторую проверку, так как значение должно соответствовать предопределенный формат строки (соответствие регулярных выражений для электронной почты с использованием встроенного Django в from django.core.validators import email_re, если детали важны).

У нас есть следующее:


def some_function():
        try:
            email = account.pop('email', None)
        except KeyError as ex:
            return

        if not email:
            return

        if not email_re.match(email):
            return

        # Get/Update Or Create SurfAccount:
        surf_account, created = SurfAccount.objects.update_or_create(
            email=email,
            defaults=account
        )

        return surf_account, surfer

Однако я не уверен, что это самый идиоматический c способ выполнить всплывающее окно с проверкой в ​​сочетании с обработчиком исключений KeyError ... потому что мы можем столкнуться с TypeError, если вызовем функцию следующим образом:

surf_account, surfer = some_function()

Потому что мы просто "returning", когда проверка не проходит ...

Q.) Итак, какой самый лучший идиоматический c способ выполнить такой словарь выскочить с проверка

Ответы [ 2 ]

2 голосов
/ 26 февраля 2020

dict.pop(key, default) не будет никогда поднимать KeyError, если ключ не существует, он просто возвращает значение по умолчанию. Так что ваша попытка: кроме: бесполезна.

Это хорошо, если не использовать pop таким способом, особенно если вы ожидаете, что этот случай будет довольно распространенным.

Проблема с вашей второй запиской в том, что соглашение о вызовах вашей функции противоречиво, иногда оно возвращает два результата, а иногда не возвращает ни одного, поэтому его трудно использовать.

  • common Python идиома рекомендует, чтобы ваша функция вызвала исключение в случае недопустимого электронного письма (пропущенного или неправильного), таким образом, «счастливый путь» всегда возвращает два значения, а «несчастный путь» является обработчиком исключений, просто замените ваш голый return, вызвав подходящее исключение
  • если вы не хотите вызывать исключение по какой-либо причине, вам нужно либо изменить результат, чтобы он всегда был одним значением (например, классом данных), либо вам нужно изменить регистр ошибок, чтобы он возвращал что-то вроде None, None (что само по себе несколько рискованно в отличие от текущей проблемы, поскольку if some_function() всегда пройдет).
1 голос
/ 26 февраля 2020

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

try:
    email = account.pop('email')  # no default value here, so exception can occur
except KeyError as ex:
    return None, None

Тем не менее, лучший подход - вызвать конкретное исключение c :

try:
    email = account.pop('email')
except KeyError as ex:
    raise NoAccountFound() from ex

и пусть вызывающая сторона справится с этим:

try:
    some_function()
except NoAccountFound:
    print("no account found...")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...