264

ラムダ式を使用するたびに、この pep8 警告が表示されます。ラムダ式は推奨されませんか? そうでない場合、なぜですか?

4

5 に答える 5

312

あなたが実行しているPEP-8の推奨事項は次のとおりです。

ラムダ式を名前に直接バインドする代入ステートメントではなく、常に def ステートメントを使用してください。

はい:

def f(x): return 2*x 

いいえ:

f = lambda x: 2*x 

最初の形式は、結果の関数オブジェクトの名前が一般的な '<lambda>' ではなく具体的​​に 'f' であることを意味します。これは、一般的にトレースバックと文字列表現に役立ちます。代入ステートメントを使用すると、明示的な def ステートメントよりもラムダ式が提供できる唯一の利点 (つまり、より大きな式の中に埋め込むことができる) がなくなります。

名前にラムダを割り当てることは、基本的にの機能を複製するだけでdefあり、一般に、混乱を避けて明確にするために、単一の方法で何かを行うことが最善です。

ラムダの正当な使用例は、関数を代入せずに使用したい場合です。たとえば、次のようになります。

sorted(players, key=lambda player: player.rank)

一般に、これを行うことに対する主な議論は、defステートメントによってコード行が増えるということです。それに対する私の主な反応は次のとおりです。はい、それで結構です。コードゴルフをしているのでない限り、行数を最小限に抑えることはすべきことではありません。短くするよりも明確にする必要があります。

于 2014-07-29T07:31:26.803 に答える
154

これがストーリーです。2回使用していた単純なラムダ関数がありました。

a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)

これは単なる表現のためのものです。私はこれのいくつかの異なるバージョンに直面しました。

さて、物事を DRY に保つために、この共通のラムダを再利用し始めます。

f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

この時点で、私のコード品質チェッカーはラムダが名前付き関数であると文句を言うので、それを関数に変換します。

def f(x):
    return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

ここで、チェッカーは、関数の前後に 1 つの空白行が必要であると警告します。

def f(x):
    return x + offset

a = map(f, simple_list)
b = map(f, another_simple_list)

ここでは、元の 2 行の代わりに 6 行のコードがあり、可読性も Pythonic も向上していません。この時点で、コード チェッカーは関数に docstring がないことを報告します。

私の意見では、このルールは避けて、理にかなっている場合は破ったほうがよいので、あなたの判断で使用してください。

于 2016-05-27T18:14:39.970 に答える
28

Lattyware は完全に正しいです: 基本的にPEP-8は次のようなことを避けることを望んでいます

f = lambda x: 2 * x

代わりに使用する

def f(x):
    return 2 * x

ただし、最近のバグレポート(2014 年 8 月) で対処されているように、次のようなステートメントは準拠しています。

a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x

私の PEP-8 チェッカーはまだこれを正しく実装していないので、当面 E731 をオフにしました。

于 2015-01-13T17:32:28.720 に答える
0

また、def(ined) 関数を使用することさえ不可能な状況に遭遇しました。

class SomeClass(object):
  # pep-8 does not allow this
  f = lambda x: x + 1  # NOQA

  def not_reachable(self, x):
    return x + 1

  @staticmethod
  def also_not_reachable(x):
    return x + 1

  @classmethod
  def also_not_reachable(cls, x):
    return x + 1

  some_mapping = {
      'object1': {'name': "Object 1", 'func': f},
      'object2': {'name': "Object 2", 'func': some_other_func},
  }

この場合、クラスに属するマッピングを作成したかったのです。マッピング内の一部のオブジェクトは、同じ機能を必要としていました。名前付き関数をクラスの外に置くのは非論理的です。クラス本体内からメソッド (staticmethod、classmethod、または normal) を参照する方法が見つかりません。コードが実行されるとき、 SomeClass はまだ存在しません。したがって、クラスから参照することもできません。

于 2016-06-16T14:12:36.133 に答える
-2

これはクラスで機能し、ラムダ式を削除し、代わりに def を使用して、これを変更します...

    def set_every(self, every: int = 1, time_unit: int = TimeUnit.Day):
        every_func = lambda x: "*" if x == 1 else "*/" + str(x)
        if TimeUnit.has_value(time_unit):
            self.month_of_year = "*"
            self.day_of_month = "*" if time_unit != TimeUnit.Day else every_func(every)
            self.day_of_week = "*" if time_unit != TimeUnit.Week else every_func(every)

これで...

    def set_every(self, every: int = 1, time_unit: int = TimeUnit.Day):
        def every_func(x: int) -> str: return "*" if x == 1 else "*/" + str(x)
        if TimeUnit.has_value(time_unit):
            self.month_of_year = "*"
            self.day_of_month = "*" if time_unit != TimeUnit.Day else every_func(every)
            self.day_of_week = "*" if time_unit != TimeUnit.Week else every_func(every)
于 2021-08-28T23:13:43.077 に答える