LoginSignup
5
9

More than 5 years have passed since last update.

pythonで可変長引数を使うときに気をつけたいこと

Posted at

 とても初歩的な内容だが、仕事でプログラミングをしているときにどツボにハマったのでメモしておく。

可変長引数とは

 可変長引数とは、自由に引数の大きさを変更できる引数のことである。Pythonだと、引数の中身をtupple型に格納してくれる*args(arguments)と、dict型として受け取ってくれる**kargs(keyword arguments)が用意されている。
 詳しい使い方等については、以下のページに詳しい。
- 可変長引数
- Pythonの可変長引数(*args, **kwargs)の使い方

可変長引数を使うときの問題点

argsの場合

 では、本題に移ろう。まず、次のような関数を考える。

test1.py
def hoge(a,b,*c):
    print(a)
    print(b)
    print(c)

if __name__ == "__main__":
    a="Hello!"
    b="World!"
    c=["I am a","nooby","programmer!!"]
    hoge(a,b,c)
responce
Hello!
World!
(['I am a', 'nooby', 'programmer!!'],)

 この関数は、引数が3つあるが、もしそのうちの1つを忘れてしまったらどうなるだろうか?

test2.py
def hoge(a,b,*c):
    print(a)
    print(b)
    print(c)

if __name__ == "__main__":
    a="Hello!"
    b="World!"
    c=["I am a","nooby","programmer!!"]
    hoge(a,c)
responce
Hello!
['I am a', 'nooby', 'programmer!!']
()

問題なく動いてしまった。
そう、可変長引数は「変数の大きさを自由に変えられる引数」だった。言い換えれば、長さは0であっても良いことを意味する。

**kargsの場合

以上の特徴は、**kargsでも同様だが、こちらはキーワードが必要になるので比較的間違いに気づきやすいかもしれない。

test3.py
def foo(hoge,fuga,**hage):
    print(hoge)
    print(fuga)
    print(hage)

if __name__ == "__main__":
    hoge="Hello!"
    piyo="World!"
    hage=["I am a","nooby","programmer!!"]
    foo(hoge,fuga=hage[0],c=hage[1],d=hage[2])
responce
Hello!
I am a
{'c': 'nooby', 'd': 'programmer!!'}

 これは、**kargsの一部としたかったkeywordを、関数fooの2番目の引数であるfugaとしてしまったことに起因している。引数と一致させなければきちんとエラーが返る。

test5,py
def foo(hoge,fuga,**hage):
    print(hoge)
    print(fuga)
    print(hage)

if __name__ == "__main__":
    hoge="Hello!"
    piyo="World!"
    hage=["I am a","nooby","programmer!!"]
    foo(hoge,b=hage[0],c=hage[1],d=hage[2])
responce
Traceback (most recent call last):
  File "hoge.py", line 12, in <module>
    foo(hoge,b=hage[0],c=hage[1],d=hage[2])
TypeError: foo() missing 1 required positional argument: 'fuga'

対策

 以上のように、特に*argsを用いた際にケアレスミスの要因となる場合があることがわかった。以上のような問題を起こさないためには、*argsがtupple型、**kargsがdict型として格納されていることを活用して、次のようにすると良いだろう。

test5.py
def hoge(a,b,*c):
    if len(c)==0: raise TypeError("*c is not given")
    print(a)
    print(b)
    print(c)

if __name__ == "__main__":
    a="Hello!"
    b="World!"
    c=["I am a","nooby","programmer!!"]
    hoge(a,c)
responce
Traceback (most recent call last):
  File "hoge.py", line 11, in <module>
    hoge(a,c)
  File "hoge.py", line 2, in hoge
    if len(c)==0: raise TypeError("*c is not given")
TypeError: *c is not given
5
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9