2012-09-08 78 views
4

我想让我的代码不接受关键字参数就像一些bulitins也不接受关键字参数,但是,我无法这样做。这里,是根据我有限的了解我的想法: -python不接受关键字参数

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

somefunc(10,20) 

输出:

10 20 

现在,当我运行下面的(我知道这是不是有望成为关键词参数在函数定义中,但是,在看函数调用时,它看起来与调用接受关键字参数的函数时的语法相同):

somefunc(b=10,a=20) 

输出:

20 10 

我有2个问题: -

  1. 望着函数调用somefunc(b=10,a=20)而不是函数定义,这可能似乎不是的对只接受普通参数或接受关键字参数的函数的函数的调用。口译员如何区分两者?
  2. 是否有可能将表单中的任何函数转换为不与许多内建函数一样接受关键字参数?

为什么我想这样做呢? 我只是检查我是否可以做到这一点,这样我就不会错过深入了解python的任何内容。我知道python是否允许。

+0

你为什么要这样做? –

+1

我只是检查我是否可以这样做,这样我就不会错过深入理解python的任何内容。 – GodMan

回答

4

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

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

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

许多其他C函数的标题为...(... PyObject *args, PyObject *kwds),他们通过执行更复杂的验证PyArg_ParseTupleAndKeywords并将名称写入文档字符串来明确支持名称的确切列表。

编辑:提高英语

3

Looking at the function call somefunc(b=10,a=20) and not the function definition, this can seem to be either of a call to a function which accepts just normal arguments or a function which accepts keyword arguments. How does the interpreter differentiate between the two?

不知道这是不是你所问的,但如果我理解你的话,答案是“它不”。无论参数在函数中如何定义,都可以用调用函数。如果您使用关键字语法传递任何参数(例如,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,那么它将不接受关键字参数,但位置参数不能具有单独的名称。

+0

@BrenBarn:'无论函数中参数的定义如何,都可以用关键字调用函数。我明白那个。但是,我只是通过查看函数调用'somefunc(b = 10,a = 20)'来说,判断函数定义是否需要2个不同的名称:'a'和'b ',或者函数期望关键字参数。不是吗? – GodMan

+0

@GodMan:我想你正在以一种奇怪的方式使用“关键字参数”。你的意思是*变量*关键字参数(即'** kwargs')?如果是这样,那么是的,你不能说。但那不是“关键词争论”的意思;关键字参数只是由关键字定义和/或传递的参数(即使它们是明确定义的)。定义了def f(a,b)和def f(a = 2,b = 3)的函数都通过名称'a'和'b'接受不同的参数,并且在这两种情况下都可以传递这些值按位置或按关键字。 – BrenBarn

+0

@Marcin:我已经编辑澄清,你不能做的是命名位置参数,不接受通过关键字传递的值。 – BrenBarn

5

您可以使用任意参数列表来执行此操作。见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

+1 - _目前还不清楚你为什么要这么做。 - - 只是因为你能做到这一点_doesn't_这意味着它可以做到这一点。 – Kimvais

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阅读起来。

0

我觉得这是一个非常不好的Python的功能,并可能导致非常难以维护和bug的代码。假设你有一个函数:

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解决。