E731 람다 식을 할당하지 않고 def를 사용하십시오.


답변:


231

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명령문이 더 많은 코드 행을 생성 한다는 것입니다. 그것에 대한 나의 주요 반응은 다음과 같습니다. 그렇습니다. 코드 골프를하지 않는 한 줄 수를 최소화하는 것은해야 할 일이 아닙니다.


5
나는 그것이 얼마나 나쁜지 알지 못한다. 역 추적에는 여전히 잘못된 행 번호와 소스 파일이 포함됩니다. 하나는 "f"라고 말하고 다른 하나는 "람다"라고 말합니다. 람다 오류는 단일 문자 함수 이름이 아니거나 이름이 긴 이름이 아니기 때문에 스캔하기가 더 쉬울 수 있습니다.
g33kz0r

4
@ g33kz0r 글쎄, 나머지 코드의 품질이 좋지 않다고 가정하면 다음 규칙을 따르면 많은 이점을 얻지 못할 것입니다. 일반적으로, 아닙니다. 그것은 세상의 끝이 아니지만 여전히 나쁜 생각입니다.
Gareth Latty

39
이 답변은 defPEP8 검사기 를 통해 사용하는 제안 된 접근 방식을 실행할 때 얻을 수 E704 multiple statements on one line (def)있고 두 줄로 E301 expected 1 blank line, found 0
나누면

4
나는 그것이 분리되어야한다는 데 동의합니다. 내 요점은 a) 위의 답변 코드에서 분할되지 않아 E704가 발생하고 b) 분할하면 E301을 피하기 위해 그 위에 못생긴 빈 줄이 필요하다는 것입니다.
Adam Spiers

3
순수한 기능 (부작용 없음)을 강조하고 싶을 때 람다 (lambdas)를 사용하며 때로는 그룹 별과 함께 두 위치에서 동일한 기능을 사용해야하는 경우가 있습니다. 그래서 나는이 관습을 무시합니다.
manu

119

여기에 이야기가 있습니다. 두 번 사용했던 간단한 람다 함수가 있습니다.

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)

이제 검사기는 함수가 앞뒤로 하나의 빈 줄로 묶여 있어야한다고 불평합니다.

def f(x):
    return x + offset

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

여기 우리는 가독성을 높이 지 않고 파이 토닉을 증가시키지 않고 원래 2 줄 대신 6 줄의 코드를 가지고 있습니다. 이 시점에서 코드 검사기는 docstring이없는 함수에 대해 불평합니다.

제 생각에는이 규칙을 피하고 깨뜨리는 것이 좋습니다. 판단력을 사용하십시오.


13
a = [x + offset for x in simple_list]. 필요 없음 사용에 maplambda여기.
Georgy

8
@ 조지 (Georgy) 나는 x + offset한 줄 이상의 코드를 변경하지 않고 업데이트 할 수있는 추상적 인 위치로 부분 을 옮기는 것이 요점이라고 생각합니다 . 언급 한대로 목록 이해를 사용하면 x + offset방금 목록 이해에 포함 된 두 줄의 코드가 여전히 필요합니다 . 저자가 원하는대로 사람들을 끌어하기 위해, 당신은 필요 def이상 lambda.
율리우스

1
그렇다에서 @Julian def하고 lambda하나는 사용할 수 functools.partial : f = partial(operator.add, offset)다음과 a = list(map(f, simple_list)).
Georgy

어떻습니까 def f(x): return x + offset(즉, 한 줄에 정의 된 간단한 함수)? 적어도 flake8에서는 빈 줄에 대한 불만이 없습니다.
DocOc

1
@Julian 어떤 경우에는 다음과 같이 중첩 된 이해를 사용할 수 있습니다.a, b = [[x + offset for x lst] for lst in (simple_list, another_simple_list)]
wjandrea

24

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을 해제했습니다.


8
을 사용할 때도 defPEP8 검사기는로 불평 E301 expected 1 blank line, found 0하므로 빈 줄을 먼저 추가해야합니다.
Adam Spiers

1

또한 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},
  }

이 경우 클래스에 속한 매핑을 만들고 싶었습니다. 매핑의 일부 객체에는 동일한 기능이 필요했습니다. 명명 된 함수를 클래스 외부에 두는 것은 비논리적입니다. 클래스 본문 내부에서 메서드 (정적 메서드, 클래스 메서드 또는 일반)를 참조하는 방법을 찾지 못했습니다. 코드가 실행될 때 SomeClass가 아직 존재하지 않습니다. 따라서 수업에서 그것을 언급하는 것도 불가능합니다.


당신은 참조 할 수 also_not_reachable매핑 정의로SomeClass.also_not_reachable
yaccz

1
당신이 여기서 어떤 점을 만들려고하는지 모르겠습니다. 모든 함수명은 f2.7과 3.5 에서처럼 도달 할 수 있습니다
Eric

람다 함수를 제외한 모든 함수는 클래스 본문 내에서 도달 할 수 없습니다. some_mapping 객체에서 해당 함수 중 하나에 액세스하려고하면 AttributeError : type 객체 'SomeClass'에 속성 '...'이 없습니다.
simP

3
@simP는 모두 완벽하게 액세스 할 수 있습니다. 가진 사람 @staticmethod@classmethod그냥 객체가 필요하지 않습니다 SomeClass.also_not_reachable(그들은 고유 한 이름이 필요하지만). 클래스 메소드에서 액세스 해야하는 경우 다음을 사용하십시오.self.also_not_reachable
ababak

@simP 아마도 xD로 *not_reachable메소드 이름을 바꿔야 할 것입니다not_as_easily_reachable_from_class_definition_as_a_lambda
Romain Vincent
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.