web-dev-qa-db-ja.com

スター演算子とはどういう意味ですか?

Zip(*x)f(**k)のようなコードのように、Pythonでは*演算子は何を意味しますか?

  1. インタプリタの内部ではどのように扱われますか?
  2. パフォーマンスにはまったく影響しますか?速いですか遅いですか。
  3. それはいつ役に立ちますか?
  4. それは関数宣言または呼び出しの中で使われるべきですか?
525
psihodelia

一重星*はシーケンス/コレクションを位置引数に展開しますので、これを行うことができます。

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

これによりTupleが解凍され、実際には次のように実行されます。

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)

Pythonのドキュメントのセクション 4.7.4 - 引数リストの展開 も参照してください。


さらに、*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になります。ここでの*および**は、関数宣言および呼び出しの構文の一部です。

40
Ned Batchelder

私はあなたが関数呼び出しを「保存」したいときにこれが特に役に立つと思います。

たとえば、関数 '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つの場所は、Factoryオブジェクト(あなたのためにオブジェクトを作成するオブジェクト)を定義するためです。 Carオブジェクトを作成してそれらを返すクラスFactoryがあるとします。 myFactory.make_car( 'red'、 'bmw'、 '335ix')がCar( 'red'、 'bmw'、 '335ix')を作成してそれを返すようにすることができます。

def make_car(*args):
   return Car(*args)

スーパークラスのコンストラクタを呼び出したいときにも便利です。

17
Donald Miner

これは拡張呼び出し構文と呼ばれています。 のドキュメントから

構文*式が関数呼び出しに現れる場合、式はシーケンスに評価されなければなりません。このシーケンスの要素は、追加の位置引数であるかのように扱われます。位置引数x1、...、xNがあり、expressionがシーケンスy1、...、yMに評価される場合、これはM + N個の位置引数x1、...、xN、y1、...を持つ呼び出しと同じです。 ..、yM。

そして:

構文**式が関数呼び出しに現れる場合、式はマッピ​​ングとして評価されなければならず、その内容は追加のキーワード引数として扱われます。式の中に、および明示的なキーワード引数として現れるキーワードの場合、TypeError例外が発生します。

15
Mark Byers

関数呼び出しでは、シングルスターはリストを別の引数に変換します(例:Zip(*x)x=[x1,x2,x3]の場合はZip(x1,x2,x3)と同じです)。ダブルスターは辞書を別のキーワード引数に変換します(例:f(**k)k = {'x':my_x, 'y':my_y}の場合はf(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}になるでしょう) "#:。

11
sepp2k