默认参数和非常量参数的顺序

17 投票
6 回答
21400 浏览
提问于 2025-04-16 06:48

在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),但这不是我想讨论的重点。

6 个回答

2

这个功能并不是通过 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"
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)

这样,用户在想要传入除了0以外的值时,可以使用命名的start参数。(虽然命名参数不是必须的,但这样可以让代码更清晰。)

for i in range3(55, start=12)
12

好吧,range 是 C 语言写的代码,它可以做得更好一些。无论如何,你可以这样做:

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

然后相应地对这个函数进行说明。

撰写回答