web-dev-qa-db-ja.com

'key'とラムダ式を使ったpython max関数

私はOOP経歴から来て、pythonを学ぼうとしています。リストmaxの中で最大のPlayerを持つtotalScore型のインスタンスを返すためにラムダ式を使用するplayers関数を使用しています。

def winner():
    w = max(players, key=lambda p: p.totalScore)

関数は、最大Playerを持つタイプtotalScoreのインスタンスを正しく返します。私は以下の3つのことについて混乱しています。

  1. max関数はどのように機能しますか?それが取っている議論は何ですか?私は文書を見ましたが、理解できませんでした。
  2. Max関数でのキーワードkeyの使用は何ですか?私はそれがsort関数のコンテキストでも使われていることを知っています
  3. ラムダ式の意味は?それらを読むには?どうやって動くの?

これらはすべて非常に厄介な概念的な質問ですが、私が言語を理解するのに役立ちます。あなたが説明するための例を挙げることができればそれは役立ちます。ありがとう

140
Vijay

lambdaは無名関数です。次のものと同等です。

def func(p):
   return p.totalScore     

maxは次のようになります。

max(players, key=func)

しかしdefステートメントは複合ステートメントであるため、式が必要なところでは使用できません。そのため、lambdaが使用されることがあります。

lambdaは、defのreturn文に入力したものと同じです。したがって、lambda内でステートメントを使用することはできません。式だけが許可されます。


maxは何をしますか?

max(a、b、c、... [、key = func]) - > value

単一の反復可能な引数で、その最大の項目を返します。引数が2つ以上の場合は、最大の引数を返します。

だから、それは単に最大のオブジェクトを返します。


keyはどのように機能しますか?

Python 2のデフォルトではkeyはオブジェクトの型に基づいて ルールのセット に基づいてアイテムを比較します(例えば文字列は常に整数より大きいです)。

比較の前にオブジェクトを修正したり、特定の属性/インデックスに基づいて比較したりするには、key引数を使用します。

例1

簡単な例として、文字列形式の数字のリストがあるが、それらのアイテムをそれらの整数値で比較したいとします。

>>> lis = ['1', '100', '111', '2']

ここでmaxは元の値を使って項目を比較します(文字列は辞書式に比較されるので、出力として'2'が得られます)。

>>> max(lis)
'2'

整数値で項目を比較するには、keyと単純なlambdaを使用します。

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

例2:リストのリストへのmaxの適用.

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

デフォルトではmaxは最初のインデックスでアイテムを比較します。最初のインデックスが同じ場合は、2番目のインデックスと比較されます。私の例のように、すべての項目は一意の最初のインデックスを持っているので、あなたは答えとしてこれを得るでしょう:

>>> max(lis)
(4, 'e')

しかし、各項目をインデックス1の値で比較したい場合はどうなりますか。シンプル:lambdaを使う:

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

異なる型のオブジェクトを含むイテラブルの項目を比較する

混合アイテムのリスト:

lis = ['1','100','111','2', 2, 2.57]

Python 2では2つの異なる型の項目を比較することが可能です

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

しかしPython 3ではこれ以上できません

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

各オブジェクトの整数バージョンを比較しているので、これはうまくいきます。

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'
222

最大機能はどのように機能しますか?

それはイテラブルの中で "最大"の項目を探します。私はあなたがそれが何であるかを調べることができると思いますが、そうでなければ、それはあなたがループすることができるもの、すなわちリストかストリングです。

Max関数でのキーワードキーの使用は何ですか?ソート機能のコンテキストでも使用されていることを私は知っています

Keyは、maxに、イテラブル内のどのオブジェクトが他のオブジェクトより大きいかを通知するラムダ関数です。あなたが自分で作成したオブジェクトをソートしていて、整数のような明白なものではないとしましょう。

ラムダ式の意味は?それらを読むには?どうやって動くの?

それはもっと大きな質問です。簡単に言うと、ラムダは、受け渡し、他のコードで使用できる関数です。例を挙げましょう。

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

これはabの2つのオブジェクトと、関数fを取ります。各オブジェクトに対してf()を呼び出してから、それらを一緒に追加します。それで、この呼び出しを見てください:

>>> sum(2, 2, lambda a:  a * 2)
8

sum()2を取り、それにラムダ式を呼び出します。そのためf(a)2 * 2になり、これは4になります。それから、bに対してこれを行い、2つを足し合わせます。

それほど単純ではない用語では、ラムダはラムダ計算から来ています。これは、関数を返す関数の概念です。計算を表現するためのとてもクールな数学の概念。あなたは こちら について読むことができ、そして実際にそれを理解することができますこちら

ラムダは混乱を招く可能性があるので、これについてもう少し読むのがおそらくより良いです、そして、それがそれらがどれほど有用であるかすぐに明白ではありません。 こちら を確認してください。

9
charmlessCoin

非常に単純化されたバージョンのmax

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

ラムダについて:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

maxname__関数は、iterablename__から最大値を取得するために使用されます。

イテレータはリスト、タプル、辞書オブジェクトなどです。あるいはあなたが提供した例のようにカスタムオブジェクトさえも可能です。

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

そのため、key=funcでは基本的にオプションの引数keyname__を関数に渡すことができます。この引数に基づいて、指定された反復子/引数がソートされ、最大値が返されます。

lambdaname__は、擬似関数として機能するpythonキーワードです。したがって、playername__オブジェクトを渡すと、player.totalScoreが返されます。したがって、関数maxname__に渡されたイテラブルは、与えられたkeyname__オブジェクトのplayertotalScoreに従ってソートされ、最大のplayername__を持つtotalScorename__を返します。

keyname__引数が指定されていない場合、最大値はデフォルトのPythonの順序に従って返されます。

例 -

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')
5
shad0w_wa1k3r

によると ドキュメント

max(iterable [、key])
max(arg1、arg2、* args [、key])
最大の要素を繰り返し可能な、または最大の2つ以上の引数で返します。

位置引数が1つ指定されている場合、iterableは空でない反復可能(空でない文字列、Tuple、listなど)でなければなりません。イテラブルの最大の項目が返されます。 2つ以上の位置引数が指定されている場合、最大の位置引数が返されます。

オプションのkey引数は、list.sort()で使用されるような1引数の順序付け関数を指定します。 key引数を指定する場合は、キーワード形式でなければなりません(例えば、max(a、b、c、key = func))。

これが言っているのは、あなたの場合はリスト、この場合はplayersを提供しているということです。それからmax関数はリスト内のすべての項目を反復処理し、それらを互いに比較して「最大」を取得します。

想像できるように、playerのような複雑なオブジェクトでは比較のための値を決めるのが難しいので、key関数を使って各maxの値を決める方法を決めるためにplayer引数を与えます。この場合、ラムダ関数を使用して、「p内のplayersごとにp.totalscoreを取得し、それを比較のための値として使用します」と言っています。

5
Inbar Rose

maxは、最初の引数にiterableを取る関数に組み込まれています(listやTupleのように)

キーワード引数keyのデフォルト値はNoneですが、評価する関数を受け入れます。関数に基づいて反復可能と評価されるラッパーと見なします。

この辞書の例を見てください。

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

例:

>>> max(d.keys())
'sword'

Kwarg(keyへの関数)なしでイテラブルを渡すだけの場合にわかるように、それはkeyの最大値を返しています(アルファベット順)。

例キーの最大値をアルファベット順に見つける代わりに、キーの長さで最大キーを見つける必要があるかもしれません。

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

この例では、ラムダ関数は反復されるキーの長さを返すので、アルファベット順ではなく値を評価しながら、キーの最大長を追跡し、最大長のキーを返します。

例.

>>> max(d.keys(), key=lambda x: d[x])
'friend'

この例では、ラムダ関数は最大値を持つ対応する辞書キーの値を返しています

1
Gahan