Аргумент по умолчанию, альтернативный None?

Я пишу функцию примерно так:

def parse(string, default=None):
    try:
        ...  # Body of function here
    except ParseError:
        if default is not None:
            return default
        raise

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

if len(sys.argv) > 4:
    if flag.ignore_invalid:
        result = parse(sys.argv[4], None)  # Still raises error
    else:
        result = parse(sys.argv[4])

Что я пытался исправить, так это:

_DEFAULT = object()

def parse(string, default=_DEFAULT):
    ...
        if default is not _DEFAULT:
            ...

Но это похоже на то, что я слишком много думаю об этом, и кажется, что есть более простой способ сделать это.

Это делают функции any и all (разрешая None по умолчанию), но я не знаю, как это сделать.


person Community    schedule 11.05.2015    source источник
comment
object является разумным дозорным, если None не подходит - обратите внимание, что вы можете использовать default=object (то есть класс), а не default=_DEFAULT (экземпляр), чтобы сохранить дополнительное назначение. object is object, что позволяет избежать проблем с возвращаемыми значениями в нечетных реализациях __eq__. Связано: stackoverflow.com/q/1118454/3001761   -  person jonrsharpe    schedule 11.05.2015
comment
Ваш _DEFAULT — вполне разумный путь.   -  person khelwood    schedule 11.05.2015
comment
Значение по умолчанию просто должно быть значением, которое никогда не может быть допустимым аргументом, переданным вызывающей стороной. Пользовательский экземпляр работает хорошо, потому что вызывающий объект, хотя теоретически он может создать объект, равный вашему дозорному, он никогда не сможет создать объект, который is будет вашим дозорным. А если он явно вызывает метод со ссылкой на ваш сентинел, ну вряд ли это ваша проблема :)   -  person chepner    schedule 11.05.2015


Ответы (2)


Если вам не нужно часто игнорировать ParseError, я бы просто позволил parse бросать все время и ловил его только в тех местах, где мне нужно:

try:
    parse(sys.argv[4])
except ParseError:
    if not flag.ignore_invalid:
        raise

Хотя, если вы должны иметь значение по умолчанию, то решение _DEFAULT в порядке.

person Colonel Thirty Two    schedule 11.05.2015
comment
Я думаю, что рефакторинг всего моего кода был выходом. - person ; 11.05.2015

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

def parse(string, **kw):
    try:
        ...  # Body of function here
    except ParseError:
        if 'default' in kw:
            return kw['default']
        raise

недостатком является то, что вы не поймаете, если кто-то ошибется в написании default.

person thebjorn    schedule 11.05.2015