【问题标题】:Determine if a named parameter was passed确定是否传递了命名参数
【发布时间】:2010-09-20 07:18:16
【问题描述】:

我想知道是否可以确定是否在 Python 中传递了具有默认值的函数参数。 例如,dict.pop 是如何工作的?

>>> {}.pop('test')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'pop(): dictionary is empty'
>>> {}.pop('test',None)
>>> {}.pop('test',3)
3
>>> {}.pop('test',NotImplemented)
NotImplemented

pop方法如何判断第一次没有传递默认返回值?这是只能在 C 中完成的事情吗?

谢谢

【问题讨论】:

    标签: python default-value named-parameters


    【解决方案1】:

    约定通常是使用arg=None并使用

    def foo(arg=None):
        if arg is None:
            arg = "default value"
            # other stuff
        # ...
    

    检查是否通过。允许用户传递None,这将被解释为参数没有传递。

    【讨论】:

    • 如果None 也是参数的一个有意义的值,这将没有用。示例是 dict.pop 及其在未找到密钥时的行为 - 如果存在则返回第二个参数,否则引发 KeyError。
    • 在这种情况下,您可以创建一个带有对象的闭包变量。 MISSING = object(); def foo(arg=MISSING): if arg is MISSING: ...
    【解决方案2】:

    当您说“命名参数”时,我猜您的意思是“关键字参数”。 dict.pop() 不接受关键字参数,所以这部分问题没有实际意义。

    >>> {}.pop('test', d=None)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: pop() takes no keyword arguments
    

    也就是说,检测是否提供了参数的方法是使用*args**kwargs 语法。例如:

    def foo(first, *rest):
        if len(rest) > 1:
            raise TypeError("foo() expected at most 2 arguments, got %d"
                            % (len(rest) + 1))
        print 'first =', first
        if rest:
            print 'second =', rest[0]
    

    通过一些工作,并且也使用**kwargs 语法,可以完全模拟python调用约定,其中参数可以按位置或名称提供,并且多次提供参数(按位置和名称)导致一个错误。

    【讨论】:

      【解决方案3】:

      你可以这样做:

      def isdefarg(*args):
          if len(args) > 0:
              print len(args), "arguments"
          else:
              print "no arguments"
      
      isdefarg()
      isdefarg(None)
      isdefarg(5, 7)
      

      有关完整信息,请参阅calls 上的 Python 文档。

      【讨论】:

        【解决方案4】:

        我不确定我是否完全理解你想要什么;但是:

        def fun(arg=Ellipsis):
            if arg is Ellipsis:
                print "No arg provided"
            else:
                print "arg provided:", repr(arg)
        

        这样做是你想要的吗?如果没有,那么正如其他人所建议的那样,您应该使用 *args, **kwargs 语法声明您的函数并检查 kwargs 字典中的参数是否存在。

        【讨论】:

          【解决方案5】:
          def f(one, two=2):
             print "I wonder if", two, "has been passed or not..."
          
          f(1, 2)
          

          如果这是您问题的确切含义,我认为无法区分默认值中的 2 和已通过的 2。即使在inspect 模块中,我也没有找到如何实现这种区分。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-05-10
            • 2011-08-29
            • 1970-01-01
            • 2019-07-21
            • 1970-01-01
            • 2012-05-28
            • 2017-07-13
            • 1970-01-01
            相关资源
            最近更新 更多