Функция, возвращающая кортеж или нет: как красиво вызвать эту функцию?
предположим следующее:
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