2008-11-01 4 views
317

Мне было интересно узнать о лучших практиках для указания недопустимых комбинаций аргументов в Python. Я пришел через несколько ситуаций, когда у вас есть функция, как так:Какое исключение я должен поднимать при неправильных/незаконных комбинациях аргументов в Python?

def import_to_orm(name, save=False, recurse=False): 
    """ 
    :param name: Name of some external entity to import. 
    :param save: Save the ORM object before returning. 
    :param recurse: Attempt to import associated objects as well. Because you 
     need the original object to have a key to relate to, save must be 
     `True` for recurse to be `True`. 
    :raise BadValueError: If `recurse and not save`. 
    :return: The ORM object. 
    """ 
    pass 

Единственная неприятность с этим, что каждый пакет имеет свой собственный, как правило, слегка отличающиеся BadValueError. Я знаю, что в Java существует java.lang.IllegalArgumentException - хорошо ли понятно, что каждый будет создавать свои собственные BadValueError s в Python или есть другой предпочтительный метод?

ответ

348

Я бы просто поднять ValueError, если вам не требуется более конкретное исключение ..

def import_to_orm(name, save=False, recurse=False): 
    if recurse and not save: 
     raise ValueError("save must be True if recurse is True") 

Там действительно нет смысла делать class BadValueError(ValueError):pass - пользовательский класс идентичен использованию до ValueError, так почему бы не использовать это?

8

Я в основном только что видел встроенный ValueError, используемый в этой ситуации.

65

Я бы наследоваться от ValueError

class IllegalArgumentError(ValueError): 
    pass 

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

Если вам нужно поймать эту конкретную ошибку, полезно иметь имя.

+13

Прекратить писать классы и пользовательские исключения - http://pyvideo.org/video/880/stop-writing-classes – 2012-11-15 14:50:30

+21

@HamishGrubijan, что видео ужасно. Когда кто-то предлагал хорошо использовать класс, он просто блеял «Не используйте классы». Brilliant. Занятия хороши. [Но не верьте мне на слово) (http://lucumr.pocoo.org/2013/2/13/moar-classes/). – 2016-02-23 09:41:41

+5

@RobertGrant Нет, вы этого не понимаете. Это видео на самом деле не буквально «не использует классы». Речь идет о том, чтобы не слишком усложнять ситуацию. – RayLuo 2016-08-31 04:06:52

2

Я не уверен, что я согласен с наследованием от ValueError - моя интерпретация документации является то, что ValueError является только должно быть поднято ... наследуя встроенными командами от него или поднять его сам, кажется неправильной.

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

- ValueError documentation

0

Согласитесь с предложением Маркуса свернуть собственное исключение, но текст исключения должен уточнить, что проблема находится в списке аргументов, а не в отдельных значениях аргументов. Я предлагаю:

class BadCallError(ValueError): 
    pass 

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

Не должно ли это быть стандартным исключением в Python?

В общем, я бы хотел, чтобы стиль Python был немного острее, отличая плохие входы от функции (ошибка вызывающего абонента) от плохих результатов внутри функции (моя ошибка). Таким образом, может быть и BadArgumentError, чтобы отличать ошибки значения в аргументах от ошибок значения в локальных.