我试图让我的代码不接受关键字参数,就像一些bulitins也不接受关键字参数,但是,我无法这样做。在这里,根据我有限的理解,我的想法是: -
def somefunc(a,b):
print a,b
somefunc(10,20)
输出:
10 20
现在,当我运行以下内容时(我知道函数定义中不会出现关键字参数,但是,查看函数调用,它看起来与调用时的语法相同)接受关键字参数的函数):
somefunc(b=10,a=20)
输出:
20 10
我有2个问题: -
somefunc(b=10,a=20)
而不是函数定义,这似乎是对一个只接受普通参数的函数的调用或接受关键字参数的函数。口译员如何区分两者?为什么我要这样做? 我只是在检查我是否可以这样做,所以我不会错过任何深入理解python的东西。我知道python是否允许这样做。
答案 0 :(得分:8)
您可以使用任意参数列表来执行此操作。见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 :(得分:4)
ad 1)如果像somefunct(name=value, ...)
那样调用正确的名称,Python会自动验证这些名称。我不需要记住参数的确切标准顺序,并通过每个月在每次使用时查看文档来验证它太“神经质”,如果我记得一个具有良好描述性参数名称的函数,它将被测试它们被接受通过Python。相反,使用参数的正确顺序只能通过文档验证。通过命名参数调用优先于非常长的位置参数列表。因此,报告的行为是有根据的。 (简短的单字母参数“a,b”当然不能帮助解决错误。)
ad 2)一些众所周知的内置快速函数用C语言编写,具有少量固定数量的必需参数,不支持使用命名参数调用。 (例如hasattr
)
这是因为它们只使用简单的标题...(... PyObject *args)
,因此所有命名的参数都会被自动拒绝。 (Python无法反省C源代码中的参数名称。: - )
许多其他C函数都有一个标题...(... PyObject *args, PyObject *kwds)
,它们通过实现更复杂的验证PyArg_ParseTupleAndKeywords
并将名称写入docs字符串来明确支持名称的确切列表。
编辑:改进英语
答案 2 :(得分: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
,那么它将不接受关键字参数,但位置参数不能具有单独的名称。
答案 3 :(得分:3)
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。
答案 4 :(得分:0)
我认为这是一个非常糟糕的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中以某种方式解决这个问题。