Функция, возвращающая кортеж или нет: как красиво вызвать эту функцию?

предположим следующее:

def MyFunc(a):
  if a < 0:
    return None
  return (a+1, a+2, a+3)

v1, v2, v3 = MyFunc()
# Bad ofcourse, if the result was None

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


r = MyFunc()
if r:
  v1, v2, v3 = r
else:
  # bad!!
  pass

что мне не нравится в этом то, что я должен использовать одну переменную, а затем распаковать его.

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

кто-нибудь может предложить лучший дизайн?

6 ответов


как насчет поднять ArgumentError? Тогда вы могли бы try вызывая его, и иметь дело с исключением, если аргумент неверен.

Так, что-то вроде:

try:
    v1, v2, v3 = MyFunc()
except ArgumentError:
    #deal with it

Также см. katrielalex это для использования подкласса ArgumentError.


Это должно хорошо работать:

v1, v2, v3 = MyFunc() or (None, None, None)

, когда MyFunc() возвращает кортеж, он будет распакован, иначе он будет заменен на 3-кортеж None.


recursive имеет поистине шикарное и Pythonic разрешение. Но: почему вы хотите вернуться None? Python имеет способ обработки ошибок, и это путем создания исключения:

class AIsTooSmallError( ArgumentError ): pass

а то

raise AIsTooSmallError( "a must be positive." )

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


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

что в этом плохого? Последовательность-это хорошо.


если вы хотите v1, v2, v3 объекты для существования и установки значения по умолчанию в случае ошибки возвращайте значения по умолчанию самостоятельно. Это сделает вызывающий код проще, не полагаясь на вызывающего абонента, чтобы установить их вручную:

def MyFunc(a):
    if a < 0:
        # can't use a negative value; just return some defaults
        return (None, None, None)
    return (a+1, a+2, a+3)

С другой стороны, если возврат по умолчанию не подходит и отрицательный аргумент считается серьезной ошибкой, создайте исключение:

def MyFunc(a):
    if a < 0:
        # sorry, negative values are unacceptable
        raise ValueError('cannot accept a negative value')
    return (a+1, a+2, a+3)

на третий тяжело, возвращаясь None может быть предпочтительнее иногда при возврате одного объекта, как в случае с search() и match() функции re модуль. Он каким-то образом стоит между первыми двумя случаями, потому что сбой сопоставления-ожидаемый результат, в то время как объект возврата по умолчанию не был бы очень полезен.


Это похоже на предыдущий ответ. Вы можете вернуть либо экземпляр объекта, либо None

def MyFunc(a):
    class MyFuncClass(object):
        def __init__(self, **kwargs):
            self.__dict__.update(kwargs)
    if a < 0:
        return None
    return MyFuncClass(one=a+1, two=a+2, three=a+3)

o = MyFunc(1)
if o is not None:
    print o.one, o.two, o.three