python3x: parameterとして出てくる*argsと**kwargsって何を意味するの？

元々は~~というか本来は~~<a href="https://docs.python.org/2/tutorial/controlflow.html#arbitrary-argument-lists" target="_blank">`*`と`**`として成り立っている</a>。が界隈では通例として`*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`には一度その処理をしてしまうとループを終わらせてしまう](http://qiita.com/weedslayer/items/9ac165613bc896a1aaa1)という特徴があるからだと思う。思いつく対策としてはループの中でリストにためておいて__ループの外で__`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](http://qiita.com/weedslayer/items/b15cd3d244352844ba94)を起こしてしまうので`*`の後につけた名前だけで変数を取り扱うように。たまに忘れてしまうので備忘録として。

#参考にしたリンク

- [What does ** (double star) and * (star) do for Python parameters?](http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters)
- [*args and **kwargs? [duplicate]](http://stackoverflow.com/questions/3394835/args-and-kwargs)
- [How to use *args and **kwargs in Python](http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/)
- [return statement in for loop](http://stackoverflow.com/questions/5864166/return-statement-in-for-loops)
-