淺析python函數參數類型
在python函數定義時,截止目前到3.x的版本,一共有五種類型的參數:(註:該文章基於python 3.4.4) POSITIONAL_OR_KEYWORD(位置或關鍵字參數) POSITIONAL_ONLY(僅位置參數) KEYWORD_ONLY(僅關鍵字參數) VAR_POSITIONAL(任意數量的位置參數) VAR_KEYWORD(任意數量的關鍵字參數)
第一種:位置或關鍵字參數:
先上文檔的定義: Parameter.POSITIONAL_OR_KEYWORD - value may be supplied as either a keyword or positional argument (this is the standard binding behaviour for functions implemented in Python.)
意思就是該參數,運行兩種方式的傳遞:位置和關鍵字。
def foo(arg1, arg2): print(arg1, arg2)#以位置參數傳遞foo('one', 'two')#output:one two#以關鍵字參數傳遞:foo(arg1='one', arg2='two')foo(arg2='two', arg1='one')#output:one twoone two#混合方式:foo('one', arg2='two')#output:one two#注意:關鍵字參數不能先於位置參數被傳遞foo(arg1='one', 'two')#output: foo(arg1='one', 'two') ^SyntaxError: non-keyword arg after keyword arg
第二種:僅位置參數: Parameter.POSITIONAL_ONLY - value must be supplied as a positional argument.
Python has no explicit syntax for defining positional-only parameters, but many built-in and extension module functions (especially those that accept only one or two parameters) accept them.
意思就是:這類僅位置參數只允許接收位置參數傳遞,目前還沒有能夠讓開發人員自行定義接收該參數的函數,簡而言之,這一般會在python內建函數中出現,如:
abs(-1)#1abs(a='-1')#TypeError: abs() takes no keyword arguments
第三種:僅關鍵字參數: Parameter.KEYWORD_ONLY - value must be supplied as a keyword argument. Keyword only parameters are those which appear after a “*” or “*args” entry in a Python function definition.
意思就是:該參數只能通過關鍵字方式傳遞,且定義在 ” * ” 或 ” *args “後面。例如:
def foo(arg1, *, arg2): print(arg1, arg2)foo('one', arg2='two')#one twofoo('one', 'two')#TypeError: foo() takes 1 positional argument but 2 were givenfoo('one')#TypeError: foo() missing 1 required keyword-only argument: 'arg2'#綜上:當你定義了一個僅關鍵字參數時,必須傳入該參數並且只能用關鍵字方式傳遞,即索引值對方式。
第四種:任意數量的位置參數 Parameter.VAR_POSITIONAL - a tuple of positional arguments that aren’t bound to any other parameter. This corresponds to a “*args” parameter in a Python function definition.
這種參數就是一個星號” * “的參數了,就是可以接受任意數目的參數,這些參數將會被放在元組內提供給函數。
def foo(arg1, arg2, *arg3): print(arg1, arg2, arg3)foo('doc', 'txt', 'png', 'exe', 'jpeg')#doc txt ('png', 'exe', 'jpeg')#若傳入一個元祖提供給 *arg3 呢。foo('doc', 'txt', ('png', 'exe', 'jpeg'))#doc txt (('png', 'exe', 'jpeg'),)#所以要用*tuple的方式傳入元祖給 *arg3foo('doc', 'txt', *('png', 'exe', 'jpeg'))#doc txt ('png', 'exe', 'jpeg')
第五種:任意數量的關鍵字參數: Parameter.VAR_KEYWORD - a dict of keyword arguments that aren’t bound to any other parameter. This corresponds to a “**kwargs” parameter in a Python function definition.
這種參數就是兩個星號”**”的參數了,意思就是把上面那種單個星星參數可以接受位置參數的方式,變化成只能接受索引值對的方式即關鍵字方式傳入,並放在字典內提供給函數:
def foo(arg1, arg2, **arg3): print(arg1, arg2, arg3)foo('doc', 'txt', a='png', b='jpeg')#doc txt {'a': 'png', 'b': 'jpeg'}#同單個星號一樣,若需要傳入字典呢。foo('doc', 'txt', {'a':'png', 'b'='jpeg'})#TypeError: foo() takes 2 positional arguments but 3 were given#用*試試。foo('doc', 'txt', *{'a':'png', 'b'='jpeg'})#TypeError: foo2() takes 2 positional arguments but 4 were given#用**試試foo('doc', 'txt', **{'a':'png', 'b'='jpeg'})#doc txt {'a': 'png', 'b': 'jpeg'}#綜上,當需要將字典傳入任意數量的關鍵字參數時,需要用**dict的方式傳入。
總結:部分引用自該博主的部落格
總結:五種參數形式中僅有第二種Python沒有提供定義的方法,其他四種在定義的時候也需要注意,定義的時候應該根據Python的解析規律進行定義,其中:
位置或關鍵字參數(POSITIONAL_OR_KEYWORD)應該在最前面,其中,沒有預設值的應該在有預設值的參數前面
僅關鍵字參數(KEYWORD_ONLY)應放在任意數量位置參數(VAR_POSITIONAL)後面
任意數量位置參數(VAR_POSITIONAL)應該放在所有位置或關鍵字參數的後面
任意數量關鍵字參數(VAR_KEYWORD)應該放在任意數量位置參數的後面
*順序如下(POSITIONAL_OR_KEYWORD, VAR_POSITIONAL, KEYWORD_ONLY, VAR_KEYWORD)
**注意:任意數量位置參數和任意數量關鍵字參數只能在定義中定義一次。
def func(arg1, arg2='default', *args, **kwargs): out= "arg1=%s, arg2=%s, args=%s, kwargs=%s" % (arg1, arg2, args, kwargs) print(out)func(1) ## correctfunc(1,2) ## correctfunc(1,2,3,4) ## correctfunc(1,2,3,4,x=1,y=2) ## correctfunc(1,2,x=1) ## correctfunc(x=1) ## wrongfunc(arg1=1) ## correctfunc(1,x=1) ## correct#outputarg1=1, arg2=default, args=(), kwargs={}arg1=1, arg2=2, args=(), kwargs={}arg1=1, arg2=2, args=(3, 4), kwargs={}arg1=1, arg2=2, args=(3, 4), kwargs={'y': 2, 'x': 1}arg1=1, arg2=2, args=(), kwargs={'x': 1}arg1=1, arg2=default, args=(), kwargs={}wrongarg1=1, arg2=default, args=(), kwargs={'x': 1}#而加上僅位置參數就簡單了,那就是每次都必須傳入僅位置參數,否則會報錯:def func(arg1, arg2='default', *args, arg3, **kwargs): out= "arg1=%s, arg2=%s, args=%s, arg3=%s, kwargs=%s" % (arg1, arg2, args, arg3, kwargs) print(out)func(1)#wrongfunc(1, arg3=2)#rightfunc(1, 2, 3, 4, arg3=5, x=1,y=2)#right#outputwrongarg1=1, arg2=default, args=(), arg3=2, kwargs={}arg1=1, arg2=2, args=(3, 4), arg3=5, kwargs={'y': 2, 'x': 1}