Идиоматическое распаковка Python или False - PullRequest
0 голосов
/ 11 марта 2011

Если функция возвращает список из двух значений или кортеж в случае успеха или False при ошибке, как лучше всего распаковать список возврата в две переменные, одновременно проверяя значение False?

def get_key_value():
  if (cond != True):
    return False
  return [val1, val2]

# Call it
# How can I also check for False while unpacking?
key, value = get_key_value()

Ответы [ 4 ]

4 голосов
/ 11 марта 2011

Включение замечательного комментария @Felix Kling в ответ.

Если неспособность найти пару (ключ, значение) указывает на какой-то сбой системы, было бы лучше выдать исключение.Если ваша ошибка на самом деле не попадает ни в одно из стандартных исключений , вы должны создать собственный новый тип исключения.

cond != True лучше записать как not cond.Также лучше не создавать список, если в этом нет необходимости.

class DataNotFound(Exception): pass

def get_key_value():
  if not cond:
    raise DataNotFound("Couldn't find it!")
  return val1, val2

try:
    key,value = get_key_value()
except DataNotFound:
    #handle the failure somehow
    key, value = 'ERROR', 'ERROR'
3 голосов
/ 11 марта 2011

Это подпадает под политику «Проще просить прощения, чем разрешения» Python. Я избегаю перехватывать TypeError в вашей функции, на случай, если возникнут другие непредвиденные проблемы.

data = get_key_value()
try:
   key, value = data
except TypeError:
   #handle the failure somehow
   key, value = 'ERROR', 'ERROR'
1 голос
/ 11 марта 2011

У вас проблемы, потому что вы смешиваете типы возвращаемых данных. То, что ты можешь, не означает, что ты должен.

Хотя я согласен с другими здесь, что исключение является одним из подходящих способов, оно может зависеть от того, ожидаете ли вы найти действительный ключ и значение большую часть времени. Если это так, используйте исключение (что-то вроде KeyError), чтобы указать, что функция не выполнена. Но если вы ожидаете, что он выйдет из строя с высокой скоростью, вы, возможно, не захотите использовать исключение. В этом случае верните что-то вроде [None, None] из get_key_value, и тогда ваш код вызова будет выглядеть так:

key, value = get_key_value()
if key:
    # take action
else:
    # handle the error appropriately
1 голос
/ 11 марта 2011

Я не думаю, что - это идиоматический способ сделать это - не в последнюю очередь потому, что функция, которая ведет себя таким образом, сама по себе неидиоматична. Если вам нужно сделать это, я предлагаю вам просто использовать тот факт, что ваш двухэлементный список или кортеж является «истинным», а не «ложным» значением (это не терминология Python, но это полезно):

pair_or_false = get_key_value()
if pair:
    key,value = val
else:
    # handle failure in whatever way

Очевидная альтернатива - рассматривать не найденный случай как исключение:

try:
    key,value = get_key_value()
except TypeError:
    # deal with not-found case

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

...