Порядок аргументов по умолчанию и не по умолчанию

В Python я понимаю, что аргументы по умолчанию выводятся в конце и что аргументы, отличные от значения по умолчанию, не могут следовать аргументу по умолчанию. Это нормально. Как например:

>>> def foo(x=0, y):
        return x, y
SyntaxError: non-default argument follows default argument

Это нормально, как ожидалось.

Однако, как насчет того случая, когда я хочу, чтобы первый аргумент был по умолчанию? Как, например, как видно из приведенного выше кода, x должен быть первым аргументом и должен иметь значение по умолчанию 0.

Можно ли это сделать? Я спрашиваю, потому что даже в функции range я предполагаю, что это что-то вроде этого:

def range(start=0, end):
    pass

Итак, как это делается, и если это невозможно, как это реализовано range? Обратите внимание, что я настаиваю на том, чтобы первый аргумент был по умолчанию, вот и вся цель. Я использую range в качестве примера, потому что он идеально подходит для моей проблемы. Конечно, можно было бы реализовать range как def range(end, start=0), но это не так.

Ответы

Ответ 1

Ну, range - это код C, который может сделать это немного лучше. В любом случае вы можете сделать это:

def range(start, stop=None):
    if stop is None: # only one arg, treat stop as start ...
        stop = start
        start = 0
    ...

и соответствующим образом документируйте функцию.

Ответ 2

Он не реализован range. Вы можете использовать *args или **args и обрабатывать кортеж или dict, как хотите. Например:

def f (* args): если len (args) == 1:    print ", считая, что первый по умолчанию" elif len (args) == 2:    print "были переданы два аргумента" еще:    распечатать "Жаловаться" 

Ответ 3

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

def range1(value, end=None):
    if end == None:
        end = value
        value = 0
    return _generate_range_values(value, end)

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

def range2(*args):
    if len(args) == 1:
        start = 0
        end = int(args[0])
    elif len(args) == 2:
        start = int(args[0])
        end = int(args[1])
    return _generate_range_values(start, end)

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

def range3(end, start=0):
    return _generate_range_values(start, end)

Затем пользователи назовут его с помощью именованного аргумента start, если они захотят что-то, кроме 0. (Хотя именованный аргумент не требуется, он сохраняет код в явном виде.

for i in range3(55, start=12)

Ответ 4

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

def Range(start=0, end=None):
    if end is None:
        raise AttributeError("end value not specified")
     pass

Ответ 5

У меня нет кода для диапазона, но я уверен, что он выполняет этот трюк:

def range(start, stop=None, step=1):
    if stop is None:
        start, stop = 0, start
    ...

изменить: Исправлен код на комментарий к Мартино.