Функция возвращает кортеж или None: как хорошо называть эту функцию?
Предположим следующее:
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, так что вызывающий может красиво распаковать....
Кто-нибудь может предложить лучший дизайн?
Ответы
Ответ 1
Как насчет повышения ArgumentError
? Затем вы можете try
вызвать его и обработать исключение, если аргумент неверен.
Итак, что-то вроде:
try:
v1, v2, v3 = MyFunc()
except ArgumentError:
#deal with it
Также см. ответ katrielalex для использования подкласса ArgumentError.
Ответ 2
Это должно хорошо работать:
v1, v2, v3 = MyFunc() or (None, None, None)
Когда MyFunc()
возвращает кортеж, он будет распакован, иначе он заменит 3-кортеж None
.
Ответ 3
recursive
имеет действительно элегантное и питоновское решение. НО: зачем вы хотите вернуть None
? У Python есть способ обработки ошибок, и это связано с созданием исключения:
class AIsTooSmallError( ArgumentError ): pass
а затем
raise AIsTooSmallError( "a must be positive." )
Причина, по которой это лучше, заключается в том, что возврат значения означает, что вы завершили обработку и передаете ответ. Это нормально, если вы сделали некоторую обработку, но это глупо, если вы немедленно возвращаете None
.
Ответ 4
Другим решением является то, что функция может возвращать кортеж, полный Nones, так что вызывающий может красиво распаковать....
Что не так с этим? Согласованность - это хорошо.
Ответ 5
Если вы хотите, чтобы объекты 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
. Это как-то стоит между первыми двумя случаями, потому что совпадение неудачи является ожидаемым результатом, в то время как объект возврата по умолчанию в любом случае не будет очень полезен.
Ответ 6
Это похоже на предыдущий ответ. Вы можете вернуть экземпляр объекта или 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