2010-08-10 4 views
11

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

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

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

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

ответ

13

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

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

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

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

+0

+1 Ударьте меня на удар! – katrielalex

+1

Это приятно, но меня всегда беспокоят накладные расходы на сбор и обработку исключений. –

8

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

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

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

+0

Я не вижу, как это лучше, чем возвращать кортеж 'None'. – Skilldrick

+2

@Skilldrick: Это мило! – katrielalex

+0

Если это лучше, это, вероятно, потому, что это не требует изменения содержимого функции. – recursive

8

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

class AIsTooSmallError(ArgumentError): pass 

, а затем

raise AIsTooSmallError("a must be positive.") 

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

+0

Путь впереди ya :) Но большие умы ... – Skilldrick

+0

+1: не возвращайте None, чтобы указать ошибку. – nosklo

+0

Хех. Как и ты. Но я подклассифицировал 'ArgumentError'! – katrielalex

3

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

Что случилось с этим? Согласованность - это хорошо.

+0

Согласен. Фактически таким образом он поддерживает обратную подпись функции. +1 – simplyharsh

+2

Поддержание возвратных подписей является soooo static;) – Skilldrick

+0

@Skilldrick: По моему опыту, последовательная обратная подпись способствует динамизму, позволяя оставаться невежественными глупыми деталями и исключениями. Но я просто ленив. –

1

Если вы хотите, чтобы объекты 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 модуля. Это как-то стоит между первыми двумя случаями, потому что совпадение неудачи является ожидаемым результатом, в то время как объект возврата по умолчанию не будет очень полезен в любом случае.

1

Это похоже на предыдущий ответ. Вы можете вернуть экземпляр объекта или 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 
Смежные вопросы