元々はというか本来は*
と**
として成り立っている。が界隈では通例として*args
と**kwargs
として表記されているだけらしい。主な違いは変数の補完の仕方がtuple
かdictionary
かというだけの違い。
#何に役に立つのか
##*args
def foo(*args):
for a in args:
print a
foo(1) #1
foo(1,2,3) #1\n2\n3\n
仮の引数として*args
といれおけば、関数作成中に「引数をいくつ取るかまだ未定」なんていう時に
args
がtupleのプレースホルダーとして入ってきた引数全てを引き取る役割を果たしてくれる。
def test_var_args_call(arg1, arg2, arg3):
print ("arg1:", arg1)
print ("arg2:", arg2)
print ("arg3:", arg3)
args = ("two", 3)
test_var_args_call(1, *args)
#result
arg1: 1
arg2: two
arg3: 3
先にargs
変数を用意しておいて後から*args
でかぶせるイメージ。最初のparameter
:1 はarg1
として受け取り、残りは全てarg2
とarg3
の中に配置される。ちなみにこうやって最初に引数の数を指定して後から関数で入れていく場合は最初に定義した関数が受け取れる引数の数の分だけのみしか受け取れないので注意。def function(arg1, *args)
であれば最初の一つ目だけarg1
に行き残りは全て*args
が引き取る。
def test_var_args(farg, *args):
print "formal arg:", farg
for arg in args:
print "another arg:", arg
test_var_args(1, "two", 3)
#result
formal arg: 1
another arg: two
another arg: 3
こういう使い方をしたい場合は引数が何個来るかわからないことが多いのでfor loop
などで「出てきた数分だけxの処理を行う」としてしまったほうが楽。細かいことではあるがここでprint
の代わりにreturn
を使うと最初の一つだけしか表示されない。その理由は恐らくreturn
には一度その処理をしてしまうとループを終わらせてしまうという特徴があるからだと思う。思いつく対策としてはループの中でリストにためておいて__ループの外で__return statement
を実行する。
def test_var_args(farg, *args):
print("formal arg:", farg)
for arg in args:
print("another arg:", arg)
return arg
#result
formal arg: 1
another arg: two
another arg: 3
3
こんな感じで無理矢理やってみたが最後の3しか出せなかった。理由はarg
の最後が3にくっついたままループが終わっているからだ。
The for-loop runs each statement in it for however so many times.. if one of your statements is a return, then the function will return when it hits it. This makes sense in, for example, the following case:
def get_index(needle, haystack):
for x in range(len(haystack)):
if haystack[x] == needle:
return x
Here, the function iterates until it finds where the needle is in the haystack, and then returns that index (there's a builtin function to do this, anyways). If you want the function to run for however many times you tell it to, you have to put the return AFTER the for-loop, not inside it, that way, the function will return after the control gets off the loop
def add(numbers):
ret = 0
for x in numbers:
ret = ret + x
return ret # needs to be outside the loop
##**kwargs
一言でまとめると、*
がtupleで変数を管理するのに対し**
はdictionaryとして保存する。つまりkey
とvalue
の2つを引数として取ることができる。
def bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])
bar(name="your mom", age=12, hotness=1) #hotness 1\nage 12\nname your mom
##*l
*args
と**kwargs
に加えて*l
というイディオムもある。主な使われ方は変数として受け取ったリストを開いて中身を取り出してtuple
の中に保存してくれる。やり方は変数l
の値にリストを加え(もしくは定義しておいて後で送るetc)、そのままfunc(*l)
で呼んであげるだけだ。ただ呼ぶ方の関数にも同じ数のparameter
を用意させる必要がある。
def foo(a, b):
print(a, b)
l = [1, 2]
foo(*l) #1, 2
#追記
ちなみに*args
も**kwargs
も関数を受け取るターゲットとしか受け取ることができない。どういうことかというと
def make_averaged(*args):
return *args / len(str(*args))
# causes syntax error
syntax errorを起こしてしまうので*
の後につけた名前だけで変数を取り扱うように。たまに忘れてしまうので備忘録として。
#参考にしたリンク