【问题标题】:python not accept keyword argumentspython不接受关键字参数
【发布时间】:2012-09-08 18:47:25
【问题描述】:

我正在尝试使我的代码不接受关键字参数,就像某些 bulitins 也不接受关键字参数一样,但是我无法这样做。以下是我根据我有限的理解的想法:-

def somefunc(a,b):
    print a,b

somefunc(10,20)

输出:

10 20

现在,当我运行以下命令时(我知道这不应该是函数定义中的关键字参数,但是,查看函数调用,它似乎与调用 a 时的语法相同接受关键字参数的函数):

somefunc(b=10,a=20)

输出:

20 10

我有 2 个问题:-

  1. 查看函数调用somefunc(b=10,a=20) 而不是函数定义,这似乎是对仅接受普通参数的函数或接受关键字参数的函数的调用。口译员如何区分两者?
  2. 是否可以将我们的任何函数转换为某种形式,使其不像许多内置函数那样接受关键字参数?

我为什么要这样做? 我只是在检查我是否可以做到这一点,这样我就不会错过任何深入理解 python 的东西。我知道python是否允许这样做。

【问题讨论】:

  • 你为什么要这样做?
  • 我只是在检查我是否可以做到这一点,这样我就不会错过任何深入理解python的东西。

标签: python keyword-argument


【解决方案1】:

您可以使用任意参数列表来执行此操作。见http://docs.python.org/tutorial/controlflow.html#arbitrary-argument-lists

例如:

def somefunc(*args):
    print args[0], args[1]

无关键字调用:

somefunc(10,20)

给予:

10 20

用关键字调用:

somefunc(a=10,b=20)

给出错误:

TypeError: someFunc() got an unexpected keyword argument 'a'

目前尚不清楚您为什么要这样做。

【讨论】:

  • +1 - 不清楚你为什么要这样做。 - 只是因为你可以做到不 表示可以这样做。
【解决方案2】:

ad 1) 如果正确的名称被称为somefunct(name=value, ...),Python 会自动验证它们。我不需要记住参数的确切标准顺序,并且通过在每次使用时每个月查看文档来验证它是否过于“神经质”,如果我记得一个具有很好的参数描述性名称的函数并且它将被测试它们是否被接受通过 Python。相反,使用参数的正确顺序只能通过文档来验证。通过命名参数调用优于非常长的位置参数列表。因此,报告的行为是有根据的。 (当然,短的单字母参数“a,b”无助于防止错误。)

ad 2) 一些众所周知的 C 语言内置快速函数,其所需参数的数量很少,不支持使用命名参数调用。 (例如hasattr

这是因为它们只使用简单的标头...(... PyObject *args),因此所有命名参数都会被自动拒绝。 (Python 永远无法自省 C 源代码中的参数名称。:-)

许多其他 C 函数都有一个标头 ...(... PyObject *args, PyObject *kwds),它们通过实现更复杂的验证 PyArg_ParseTupleAndKeywords 并将名称写入文档字符串来显式地支持精确的名称列表。


编辑:Positional-only parameters 可以在 Python 3.8 中通过新的函数参数语法 / 来指示某些函数参数必须按位置指定,不能用作关键字参数。

def somefunc(a, b, /):
    print(a, b)

【讨论】:

    【解决方案3】:

    查看函数调用 somefunc(b=10,a=20) 而不是函数定义,这似乎是对仅接受普通参数的函数或接受关键字参数的函数的调用。口译员如何区分两者?

    不确定这是否正是您要问的,但如果我理解正确,答案是“不是”。无论函数中的参数如何定义,您都可以使用关键字调用函数。如果您使用关键字语法(例如,f(a=...))传递任何参数,Python 会将相应的值绑定到函数定义中具有相同名称的参数。是否定义了默认值并不重要。这两种函数定义不会创建不同“种类”的参数,只是一些参数可能具有默认值,而另一些可能没有。所以不管你是def f(a)还是def f(a=2),你仍然可以做f(a=...)。唯一的限制是您必须首先传递/定义位置参数(例如,您不能执行def f(a=2, b)f(a=2, 3))。另见this answer

    至于你问题的第二部分,我不知道有什么方法可以阻止 Python 函数接受命名参数的关键字传递值。如果您只定义*args,那么它将不接受关键字参数,但位置参数不能有单独的名称。

    【讨论】:

    • @BrenBarn:You can call the function with keywords no matter how the arguments are defined in the function。我明白那个。但是,我的意思是,仅通过查看函数调用 somefunc(b=10,a=20),判断函数定义是否需要两个不同的参数名称:ab,或者函数是否需要关键字参数,可能会令人困惑.不是吗?
    • @GodMan:我认为您以一种奇怪的方式使用“关键字参数”。您的意思是 variable 关键字参数(即**kwargs)吗?如果是这样,那么是的,你不能说。但这不是“关键字参数”的意思;关键字参数只是由关键字定义和/或传递的参数(即使它们是显式定义的)。 def f(a, b)def f(a=2, b=3) 定义的函数都接受名称为 ab 的不同参数,在这两种情况下,您都可以按位置或关键字传递这些值。
    • @Marcin:我进行了编辑以澄清您不能做的是命名位置参数不接受关键字传递的值。
    • @BrenBarn 太棒了。没有更多的投票,因为我首先投票给你的答案;)
    【解决方案4】:

    在 Python 中,关键字参数和位置参数之间没有如此明显的区别。其实就是这么简单:

    位置参数按在函数调用中列出的顺序进行解析 关键字参数可以以任何顺序添加,但不能在之前位置参数。

    所以,如果你有这个:

    def foo(x):
        pass
    

    你可以这样做:

    foo(1) # positional
    foo(x=1) # keyword
    

    但是您不能使用foo(),因为您没有提供默认值。

    同样,如果你有这个:

    def foo(x,y='hello'):
        pass
    
    foo(1) # this works fine
    foo() # this is invalid, as an argument without a default isn't passed
    foo(y='hello',1) # error - positional arguments come before keyword arguments
    

    别忘了阅读arbitrary argument lists

    【讨论】:

      【解决方案5】:

      我认为这是一个非常糟糕的 Python 功能,并且可能导致代码非常难以维护和错误。假设你有一个函数:

      def myurl(x, y):
          url = "{}:{}".format(x, y)
          return url
      

      虽然用关键字参数替换位置看起来是个好主意,但永远不要这样做。我很惊讶没有 Python 选项可以阻止使用关键字参数调用此函数:

      >> print myurl(x="localhost", y=8080)
      

      如果有人发现这个库写成这样会更具可读性:

      def myurl(hostname, port):
          url = "{}:{}".format(hostname, port)
          return url
      

      那么使用关键字调用 myurl(x="localhost", y=8080) 的其余代码将失败:

      TypeError: myurl() got an unexpected keyword argument 'x'
      

      这意味着你的局部函数变量突然变成了全局变量!我希望 Python 3 能以某种方式解决这个问题。

      【讨论】:

        猜你喜欢
        • 2021-10-10
        • 2015-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-01
        • 2020-05-17
        • 2015-02-14
        相关资源
        最近更新 更多