【问题标题】:Order of default and non-default arguments默认和非默认参数的顺序
【发布时间】:2011-05-07 11:17:15
【问题描述】:

在 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),但这不是重点。

【问题讨论】:

  • 如你所知,真正的答案是range 是一个 C 函数,由于某种原因它没有与 python 相同的规则(很高兴知道为什么)。人们可能会因为我的建议而讨厌我,但我之所以这样做是为了范围,因为我对事物的顺序有一个糟糕的记忆。 Imo 这应该不是问题,所以我正在修复它:range(*{'start':0,'stop':10,'step':2}.values())

标签: python argument-passing


【解决方案1】:

如果你真的想要,你可以自己处理异常

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

【讨论】:

    【解决方案2】:

    嗯,range 是 C 代码,它可以做得更好。无论如何,你可以这样做:

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

    并相应地记录函数。

    【讨论】:

    • 与我的答案几乎相同,但更清晰且提前了五分钟。所以,+1。
    • 可能想要添加一个step 参数以与内置保持一致。
    • 是否有构造函数或方法来提高 same TypeError: <xxx> takes no keyword arguments 例如。 range(start=1) 会加薪吗?或者 '... 接受 ... arguments ... given' TypeError 呢?我可以养同样的吗?我问是因为我确实希望模仿它是否可以提出确切的问题。在不太可能的情况下,python 会更改消息(例如一些自定义的本地化构建或其他内容),我希望我的会相应更改。
    【解决方案3】:

    range 没有实现。您可以使用 *args**args 并根据需要处理元组或字典。例如:

    定义 f(*args): 如果 len(args) == 1: print "假设第一个是默认的" elif len(args) == 2: print "通过了两个参数" 别的: 打印“投诉”

    【讨论】:

      【解决方案4】:

      有几种方法。第一个是切换函数中的参数,如果某些参数是“无”。这样就可以了。

      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)
      

      【讨论】:

      • +1 尽管我不明白为什么你觉得有必要在 args[x] 上使用 int()range2() 中而不是在其他地方。没有必要(尽管它确实允许该版本接受浮点和字符串参数,如 3.14"42")。
      • 回想起来,我不确定为什么我在其中一个示例中使用 int() 而不是其他示例。如果内置的 range() 函数得到除整数参数之外的任何内容,它将引发错误。
      【解决方案5】:

      我没有范围的代码,但我确信它会执行这种技巧:

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

      编辑:根据 martineau 的评论更正了代码。

      【讨论】:

        【解决方案6】:

        对于第一个默认值参数后跟其他参数的函数:

        def fn(first=value, *rest):
            # code
        

        例如:

        def fn(first=1, *rest):
            print(first)
        
        fn()
        fn(11, 2, 3)
        >>>
        1
        11
        

        【讨论】:

          猜你喜欢
          • 2019-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-14
          • 2012-08-01
          • 1970-01-01
          • 2013-05-31
          • 2020-09-04
          相关资源
          最近更新 更多