そのため、*args
と**kwargs
の概念には苦労しています。
今のところ、私は次のことを学びました。
*args
= 引数のリスト - 位置引数として。**kwargs
= 辞書 - そのキーは個別のキーワード引数になり、値はこれらの引数の値になります。これがどのようなプログラミング作業に役立つのか、私には理解できません。
たぶん。
リストや辞書を関数の引数として入力し、同時にワイルドカードとして入力することで、あらゆる引数を渡すことができるようになるのではないでしょうか?
どのように *args
や **kwargs
が使われるかを説明する簡単な例はありますか?
また、私が見つけたチュートリアルでは、単に "*"と変数名を使っていました。
*argsと
*kwargsは単なるプレースホルダーなのでしょうか、それともコードの中で正確に
argsと
**kwargs`を使うのでしょうか?
構文は *
と **
です。 名前の *args
と **kwargs
は慣習的なものですが、これを使わなければならないというハードルはありません。
関数に渡す引数の数がわからないときに *args
を使います。つまり、関数に任意の数の引数を渡すことができます。 例えば、以下のようになります。
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage
同様に、**kwargs
は、事前に定義していない名前付き引数を扱うことができます。
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
これらを名前付き引数と一緒に使うこともできます。 明示的な引数は最初に値を取得し、それ以外はすべて *args
と **kwargs
に渡されます。 名前付き引数はリストの最初に来ます。 例えば、以下のようになります。
def table_things(titlestring, **kwargs)
同じ関数定義の中で両方を使うこともできますが、*args
が **kwargs
の前になければなりません。
また、関数を呼び出す際には、*
と**
の構文を使用することができます。 たとえば、以下のようになります。
>>> def print_three_things(a, b, c):
... print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
このケースでは、アイテムのリスト(またはタプル)を受け取り、それをアンパックします。このようにして、関数の引数と一致させています。 もちろん、関数定義と関数呼び出しの両方に *
を入れることもできます。
*args
と **kwargs
の使用が非常に便利なのは、サブクラスの作成時です。
class Foo(object):
def __init__(self, value1, value2):
# do something with the values
print value1, value2
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print 'myfoo'
super(MyFoo, self).__init__(*args, **kwargs)
この方法では、Fooについてあまり知らなくても、Fooクラスの動作を拡張することができます。これは、変更される可能性のある API に合わせてプログラミングしている場合に非常に便利です。MyFoo は Foo クラスにすべての引数を渡すだけです。
*argsと
kwargsまたは
kw`という名前は、純粋に慣習的なものです。お互いのコードを読みやすくするためのものです。
これが便利なのは、structモジュールを使うときです。
struct.unpack()はタプルを返すのに対し、
struct.pack()は可変の引数を使います。データを操作する際には、タプルを
struck.pack()` に渡すことができると便利です。
tuple_of_data = struct.unpack(format_str, data)
... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)
この機能がなければ,次のように書かなければならないでしょう。
new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)
これはつまり、format_strが変更されてタプルのサイズが変更された場合、私は戻ってこの長い行を編集しなければならないということです。