Порядок аргументов default и non-default
в Python я понимаю, что аргументы по умолчанию приходят в конце и что аргументы не по умолчанию не могут следовать аргументу по умолчанию. Это прекрасно. Например:
>>> def foo(x=0, y):
return x, y
SyntaxError: non-default argument follows default argument
это нормально, как и ожидалось.
однако, как насчет случая, когда я хочу, чтобы первый аргумент должен быть по умолчанию? Например, как видно из приведенного выше кода, x
должен быть первым аргументом, и он должен иметь значение по умолчанию 0.
возможно ли это сделать? Я спрашиваю, потому что даже в , Я предполагаю, что это что-то вроде этого:
def range(start=0, end):
pass
Итак, как это делается, и если это невозможно, как это реализуется range
? Обратите внимание, что я настаиваю на том, чтобы первый аргумент был по умолчанию, то есть весь смысл. Я использую range
в качестве примера, потому что она идеально подходит для моей проблемы. Конечно можно реализовать range
as def range(end, start=0)
, но дело не в этом.
5 ответов
Ну range
это код на C, который может сделать это немного лучше. В любом случае, вы можете сделать это:
def range(start, stop=None):
if stop is None: # only one arg, treat stop as start ...
stop = start
start = 0
...
и документировать функцию соответственно.
Он не реализован range
. Вы можете использовать *args
или **args
и лечить кортеж или дикт, как вы хотите. Например:
def f(*args): if len(args) == 1: print "assuming the first is default" elif len(args) == 2: print "two arguments were passed" else: print "Complaining"
есть несколько подходов. Первым было бы переключить аргументы в функции, если некоторые из аргументов "нет". Это сработает вот так.
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)
вы можете обрабатывать исключения самостоятельно, если вы действительно этого хотите
def Range(start=0, end=None):
if end is None:
raise AttributeError("end value not specified")
pass
У меня нет кода для диапазона, но я уверен, что он выполняет такой трюк:
def range(start, stop=None, step=1):
if stop is None:
start, stop = 0, start
...
edit: код исправлен в комментарии Мартино.