Order of default and non-default arguments

末鹿安然 提交于 2019-12-03 11:34:06

问题


In Python, I understand that default arguments come at the end and that non-default arguments cannot follow a default argument. That is fine. Like for example:

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

That is OK as expected.

However, what about the case when I want that the first argument should be a default one? Like for example, as is apparent from the above code, x has to be the first argument and it should have a default value of 0.

Is it possible to do this? I am asking because even in the range function, I am guessing it is something like this:

def range(start=0, end):
    pass

So how is this done and if it is not possible, how is this implemented by range? Note that I am insisting on the first argument to be default, that is the entire point. I am using range as an example because it fits my problem perfectly. Of course one could implement range as def range(end, start=0), but that is not the point.


回答1:


Well, range is C code which can do this slightly better. Anyways, you can do this:

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

and document the function accordingly.




回答2:


There are a couple approaches. The first would be to switch the arguments in the function, if some of the arguments are "None". That would work like this.

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

The other primary method would be to have your function get a list of all arguments it receives. Then it can decide what to do, based on the number of arguments.

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)

The third would be to encourage users to pass named arguments to your function, which makes the order less important.

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

Then users would call it with the named start argument when they wanted something besides 0. (Although the named argument would not be required, it keeps the code clear.

for i in range3(55, start=12)



回答3:


It is not implemented by range. You can use *args or **args and treat the tuple or the dict as you want. For example:

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"



回答4:


You can handle the Exceptions yourself if you really want that

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



回答5:


I don't have the code for range, but I'm certain it performs this kind of trick:

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

edit: Code corrected per martineau's comment.



来源:https://stackoverflow.com/questions/4137770/order-of-default-and-non-default-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!