または*
のようなコードなど、Pythonでの演算子の意味は何ですか?zip(*x)
f(**k)
- インタプリタの内部でどのように処理されますか?
- パフォーマンスに影響はありますか?速いですか遅いですか?
- いつ役に立ち、いつ役に立たないのですか?
- 関数宣言または呼び出しで使用する必要がありますか?
または*
のようなコードなど、Pythonでの演算子の意味は何ですか?zip(*x)
f(**k)
単一のスター*
は、シーケンス/コレクションを位置引数にアンパックするため、次のことができます。
def sum(a, b):
return a + b
values = (1, 2)
s = sum(*values)
これにより、タプルが解凍され、実際には次のように実行されます。
s = sum(1, 2)
ダブルスター**
は同じことを行いますが、辞書と名前付きの引数のみを使用します。
values = { 'a': 1, 'b': 2 }
s = sum(**values)
以下を組み合わせることもできます。
def sum(a, b, c, d):
return a + b + c + d
values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)
次のように実行されます:
s = sum(1, 2, c=10, d=15)
セクション4.7.4- Pythonドキュメントの引数リストの解凍も参照してください。
さらに、取る関数*x
と**y
引数を定義できます。これにより、関数は、宣言で具体的に指定されていない任意の数の位置引数や名前付き引数を受け入れることができます。
例:
def sum(*values):
s = 0
for v in values:
s = s + v
return s
s = sum(1, 2, 3, 4, 5)
またはと**
:
def get_a(**values):
return values['a']
s = get_a(a=1, b=2) # returns 1
これにより、オプションのパラメーターを宣言せずに多数指定できます。
そして再び、あなたは組み合わせることができます:
def sum(*values, **options):
s = 0
for i in values:
s = s + i
if "neg" in options:
if options["neg"]:
s = -s
return s
s = sum(1, 2, 3, 4, 5) # returns 15
s = sum(1, 2, 3, 4, 5, neg=True) # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
1つの小さなポイント:これらは演算子ではありません。演算子は、既存の値から新しい値を作成するために式で使用されます(たとえば、1 + 2は3になります。ここでの*と**は、関数宣言と呼び出しの構文の一部です。
これは、関数呼び出しを「保存」する場合に特に便利です。
たとえば、関数'add'の単体テストがあるとします。
def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
print 'test: adding', test, '==', result, '---', add(*test) == result
add(test[0], test[1])
醜いのようなことを手動で行う以外に、addを呼び出す方法は他にありません。また、変数の数が可変である場合、必要なすべてのifステートメントでコードがかなり醜くなる可能性があります。
これが役立つもう1つの場所は、ファクトリオブジェクト(オブジェクトを作成するオブジェクト)を定義する場合です。Carオブジェクトを作成して返すクラスFactoryがあるとします。あなたはそれをmyFactory.make_car('red', 'bmw', '335ix')
作成してCar('red', 'bmw', '335ix')
、それを返すようにすることができます。
def make_car(*args):
return Car(*args)
これは、スーパークラスのコンストラクターを呼び出したい場合にも役立ちます。
関数呼び出しでは、シングルスターはリストを個別の引数に変換し(たとえばzip(*x)
、と同じ) zip(x1,x2,x3)
、x=[x1,x2,x3]
ダブルスターは辞書を個別のキーワード引数に変換します(たとえばf(**k)
、と同じf(x=my_x, y=my_y)
です) k = {'x':my_x, 'y':my_y}
。
関数定義では、その逆です。単一のスターは任意の数の引数をリストに変換し、ダブルスタートは任意の数のキーワード引数を辞書に変換します。たとえばdef foo(*x)
、「fooは任意の数の引数を取り、リストxからアクセスできます(つまり、ユーザーが呼び出す場合はfoo(1,2,3)
、x
になります[1,2,3]
)」をdef bar(**k)
意味し、「barは任意の数のキーワード引数を取り、辞書kからアクセスできます」を意味します。 (つまり、ユーザーが呼び出すとbar(x=42, y=23)
、)"k
になります。{'x': 42, 'y': 23}
これは、拡張呼び出し構文と呼ばれます。ドキュメントから:
構文*expressionが関数呼び出しに含まれている場合、expressionはシーケンスに評価される必要があります。このシーケンスの要素は、追加の位置引数であるかのように扱われます。位置引数x1、...、xNがあり、式がシーケンスy1、...、yMに評価される場合、これはM + N位置引数x1、...、xN、y1 、. ..、yM。
と:
構文**expressionが関数呼び出しに含まれている場合、expressionはマッピングに評価される必要があり、その内容は追加のキーワード引数として扱われます。式と明示的なキーワード引数の両方にキーワードが表示される場合、TypeError例外が発生します。