정렬 뒤의 구문 (key = lambda :…)


답변:


162

key컬렉션의 항목을 비교하기 전에 변환하기 위해 호출되는 함수입니다. 전달 된 매개 변수 key는 호출 가능한 것이어야합니다.

를 사용 lambda하면 익명 함수 (호출 가능)가 작성됩니다. sorted호출 가능 의 경우 하나의 매개 변수 만 사용합니다. 파이썬 lambda은 매우 간단합니다. 실제로 한 가지만 수행하고 반환 할 수 있습니다.

의 구문은 lambda단어 lambda뒤에 매개 변수 이름 목록과 단일 코드 블록이옵니다. 매개 변수 목록과 코드 블록은 콜론으로 표시됩니다. 이뿐만 아니라 같은 파이썬에서 다른 구조와 유사하다 while, for, if등등. 이들은 일반적으로 코드 블록이있는 모든 명령문입니다. Lambda는 코드 블록이있는 명령문의 또 다른 인스턴스입니다.

람다의 사용과 def의 사용을 비교하여 함수를 만들 수 있습니다.

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

람다는 이름을 지정하지 않고 이것을 수행하는 방법을 제공합니다. 함수의 매개 변수로 사용하기에 좋습니다.

variable 콜론의 왼쪽에는 매개 변수의 이름이 있고 오른쪽에는 코드 블록에서 무언가를 계산하기 때문에 여기에서 두 번 사용됩니다.


10
참고 (OP에) : 이름에 람다를 할당하지 않아야합니다 (즉, 익명 함수가 아닌 다른 방식으로 사용). 이 작업을 수행하는 것을 발견하면 아마도을 사용해야합니다 def.
wim

151

나는 여기에있는 모든 대답이 sorted ()의 맥락에서 람다 함수가하는 일의 핵심을 다루고 있다고 생각하지만, 여전히 직관적 인 이해로 이어지는 설명처럼 느껴지므로 여기 2 센트가 있습니다.

완전성을 기하기 위해, 나는 명백한 선행을 언급 할 것이다 : sorted ()는 정렬 된 요소들의 목록을 반환하고 우리가 특정한 방식으로 정렬하고 싶거나 복잡한 요소들의 목록 (예를 들어 중첩 된 목록 또는 튜플 목록) 키 인수를 호출 할 수 있습니다.

저에게는 주요 논쟁에 대한 직관적 인 이해, 그것이 왜 호출 가능해야하는지, 그리고 이것을 달성하기위한 (익명적인) 호출 가능 함수로 람다를 사용하는 것이 두 부분으로 나옵니다.

  1. 람 바를 사용한다는 것은 예를 들어 제공된 부기 와 같이 전체 함수를 작성 (정의) 할 필요가 없음을 의미합니다 . Lambda 함수는 생성, 사용 및 즉시 소멸되므로 한 번만 사용할 수있는 더 많은 코드로 코드를 확장하지 않습니다. 이것은 내가 이해하는 것처럼 람다 함수의 핵심 유틸리티이며 이러한 역할에 대한 응용 프로그램은 광범위합니다. 그것의 문법은 순전히 관례에 의한 것이며, 본질적으로 일반적으로 프로그램 적 문법의 본질이다. 구문을 배우고 완료하십시오.

람다 구문은 다음과 같습니다.

람다 input_variable (s) : 맛있는 하나의 라이너

예 :

In [1]: f00 = lambda x: x/2

In [2]: f00(10)
Out[2]: 5.0

In [3]: (lambda x: x/2)(10)
Out[3]: 5.0

In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0

In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
  1. key인수 뒤에 숨겨진 아이디어 는 기본적으로 정렬하는 데 사용해야하는 목록 요소에서 'sorted ()'함수를 가리키는 일련의 명령어를 사용해야한다는 것입니다. 그것이 말할 때 key=, 실제로 의미하는 것은 : 한 번에 한 요소 (예 : e의 목록)를 통해 목록을 반복 할 때 현재 요소를 핵심 인수에서 제공하는 함수에 전달하고 사용합니다. 최종 정렬 목록의 순서를 알려주는 변환 된 목록을 작성합니다.

확인 해봐:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)

기본 예 :

sorted(mylist)

[2, 3, 3, 4, 6, 8, 23] # 모든 숫자는 작은 순서에서 큰 순서로 표시됩니다.

예 1 :

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)

[3, 3, 23, 6, 2, 4, 8] #이 정렬 된 결과가 직관적입니까?

내 람다 함수가 정렬하기 전에 (e)가 짝수인지 홀수인지 확인하도록 정렬하라는 것을 알았습니다.

하지만 기다려! 두 가지가 궁금 할 수도 있습니다. 먼저 내 확률이 내 짝수보다 먼저 오는 이유는 무엇입니까? 왜냐하면 내 주요 값이에 정렬 연산자를 사용하여 짝수를 우선 순위로 분류하는 정렬 된 함수를 알려주는 것 같습니다 x%2==0. 둘째, 왜 내 짝수는 고장입니까? 2는 6의 앞에 올까요? 이 결과를 분석하여 sorted () 'key'인수가 작동하는 방식, 특히 익명의 람다 함수와 관련하여 더 깊이 배우게됩니다.

먼저, 확률이 짝수보다 먼저 나오지만 짝수 자체는 정렬되지 않습니다. 왜 이런거야?? 문서를 읽을 수 있습니다 .

주요 함수 Python 2.4부터 list.sort ()와 sorted ()는 비교하기 전에 각 목록 요소에서 호출 할 함수를 지정하는 키 매개 변수를 추가했습니다.

여기서 줄 사이를 약간 읽어야하지만, 이것이 알려주는 것은 sort 함수가 한 번만 호출되고 key 인수를 지정하면 key 함수가 가리키는 값으로 정렬한다는 것입니다.

그렇다면 모듈로를 사용한 예제는 무엇을 반환합니까? 부울 값 : True == 1, False == 0. 정렬은이 키를 어떻게 처리합니까? 기본적으로 원래 목록을 1과 0의 시퀀스로 변환합니다.

[3,6,3,2,4,8,23]은 [0,1,0,1,1,1,0]이됩니다.

이제 우리는 어딘가로 가고 있습니다. 변환 된 목록을 정렬하면 무엇을 얻습니까?

[0,0,0,1,1,1,1]

자, 이제 우리는 왜 확률이 짝수보다 먼저되는지 알 수 있습니다. 그러나 다음 질문은 왜 최종 목록에서 6이 2보다 앞에 오는가? 정렬은 한 번만 수행되기 때문에 쉽습니다. 즉, 이들 1은 여전히 ​​원래의 목록 값을 나타내며, 서로 원래 위치에 있습니다. 정렬은 한 번만 수행되며 원래 짝수 값을 낮은 순서에서 높은 순서로 정렬하기 위해 어떤 종류의 정렬 함수도 호출하지 않으므로 해당 값은 서로에 대해 원래 순서대로 유지됩니다.

마지막 질문은 다음과 같습니다. 최종 정렬 목록을 인쇄 할 때 부울 값의 순서가 원래 값으로 다시 변환되는 방법에 대해 개념적으로 어떻게 생각합니까?

Sorted ()는 (재미있는) Timsort 라는 하이브리드 정렬 알고리즘을 사용하는 내장 메소드입니다.병합 정렬과 삽입 정렬의 측면을 결합한 것입니다. 호출 할 때이 값을 메모리에 보유하고 람다 함수 (...!)에 의해 결정 된 부울 아이덴티티 (마스크)와 묶는 메커니즘이 있다는 것이 분명합니다. 순서는 람다 함수에서 계산 된 부울 ID에 의해 결정되지만 이러한 하위 목록 (1과 0)은 원래 값으로 정렬되지 않습니다. 따라서 최종 목록은 홀수 및 짝수로 구성되지만 하위 목록별로 정렬되지 않습니다 (이 경우 짝수 순서가 잘못됨). 확률이 주문된다는 사실은 원래 목록에서 우연의 일치로 이미 정렬 되었기 때문입니다. 이 모든 것으로부터의 탈취는 람다가 그 변환을 수행 할 때, 서브리스트의 원래 순서가 유지된다는 것이다.

그렇다면 이것이 어떻게 원래의 질문과 관련이 있으며, 더 중요한 것은 sorted ()를 주요 인수와 람다로 구현하는 방법에 대한 직관과 어떻게 관련이 있습니까?

그 람다 함수는 람다 함수에 의해 변환 된 부울에 값을 매핑하는 포인터 또는 중첩 된 목록의 특정 요소인지 여부에 따라 정렬 해야하는 값을 가리키는 포인터로 생각할 수 있습니다. 람다 등으로 다시 결정됩니다.

다음 코드를 실행할 때 발생하는 상황을 예측하고 시도해 보겠습니다.

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])

sorted전화는 분명히 "이 목록을 정렬하십시오"라고 말합니다. 핵심 인수는 mylist의 각 요소 (x)에 대해 해당 요소의 인덱스 1 을 반환 한 다음 원래 목록 'mylist'의 모든 요소를 람다 함수. 튜플 목록이 있으므로 해당 튜플에서 인덱싱 된 요소를 반환 할 수 있습니다. 그래서 우리는 얻는다 :

[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]

해당 코드를 실행하면 이것이 순서임을 알 수 있습니다. 정수 목록을 인덱싱하면 코드가 깨지는 것을 알 수 있습니다.

이것은 오랫동안 설명되지 않았지만, 이것이 sorted () 및 그 이상의 주요 인수로 람다 함수 사용에 대한 직관을 '정렬'하는 데 도움이되기를 바랍니다.


8
우수하고 포괄적 인 설명. 이 답변은 100 포인트가 필요합니다. 그러나 왜이 답변에 좋아하지 않는지 궁금합니다.
javed

3
깊은 설명 감사합니다. 나는 문서 와 정렬 방법을 읽었 으며 key함수 의 기본 개념은 명확하지 않았다 . sorted함수 를 이해하려고 하면 lambda구문이 이해의 길로 들어갑니다.
sanbor

3
이것이 가장 좋은 설명입니다. 이것은 실제로 어떻게 작동했는지 이해하는 데 도움이되었습니다. 람다 함수를 파악했지만 sorted () 컨텍스트에서 사용하는 것은 의미가 없습니다. 정말 도움이되었습니다. 감사합니다!
TGWaffles

2
이것은 훌륭한 답변입니다. 경례합니다.
Rajesh Mappu

2
이것은 스택 오버플로에서 가장 좋아하는 답변 중 하나입니다. 감사합니다!
AdR

26

lambda익명 함수생성 하는 데 사용되는 Python 키워드입니다 .

>>> (lambda x: x+2)(3)
5

2
왜 각각에 괄호가 있습니까?
Christopher Markieta

19
괄호는 3함수에 전달되기 때문에 주변 에 있습니다. 괄호는 람다 주위에 있으므로 표현식이로 구문 분석 되지 않으므로 함수가 아니므로 lambda x: x+2(3)유효하지 2않습니다.
Ignacio Vazquez-Abrams

"익명"기능이라는 용어가 마음에 들지 않습니다. 제 이름은 이름이 지정되지 않은 것이 사실이므로 익명은 "기술적으로"정확합니다. 차라리 그것들을 "임시 기능"이라고합니다. 그러나 나는 pedant입니다.
user5179531

12

variable의 왼쪽은 :매개 변수의 이름입니다. 의 사용 variable오른쪽에 매개 변수를 사용하고 있습니다.

다음과 거의 동일하게 의미합니다.

def some_method(variable):
  return variable[0]

5

key = lambda 를 사용한 사용법 sorted () 함수 의 또 다른 예입니다 . 튜플 목록이 있다고 가정 해 봅시다. 각 튜플에는 자동차의 브랜드, 모델 및 무게가 있으며이 튜플 목록을 브랜드, 모델 또는 무게별로 정렬하려고합니다. 람다로 할 수 있습니다.

cars = [('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000), ('bmw', 'x5', 1700)]

print(sorted(cars, key=lambda car: car[0]))
print(sorted(cars, key=lambda car: car[1]))
print(sorted(cars, key=lambda car: car[2]))

결과 :

[('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000)]
[('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100)]
[('citroen', 'xsara', 1100), ('bmw', 'x5', 1700), ('lincoln', 'navigator', 2000)]

3

lambda임의의 함수가 아닌 익명 함수입니다. 허용되는 매개 변수는 작업중인 변수와이를 정렬하는 열입니다.



1

다시 말하면, 정렬 된 함수의 키 (선택 사항. 순서를 결정하기 위해 실행할 함수. 기본값은 없음)가 함수를 예상하고 람다를 사용합니다.

람다를 정의하기 위해 정렬하려는 객체 속성을 지정하면 파이썬의 내장 정렬 함수가 자동으로 처리합니다.

여러 속성을 기준으로 정렬하려면 key = lambda x : (property1, property2)를 할당하십시오.

order-by를 지정하려면 정렬 된 함수의 세 번째 인수 (옵션 : 부울. 오름차순 정렬, True는 내림차순 정렬, 기본값은 False)로 reverse = true를 전달하십시오.


1

질문과 관련된 예제를 사용하여 간단하고 시간이 많이 걸리지 않는 답변 다음 예제를 따르십시오.

 user = [{"name": "Dough", "age": 55}, 
            {"name": "Ben", "age": 44}, 
            {"name": "Citrus", "age": 33},
            {"name": "Abdullah", "age":22},
            ]
    print(sorted(user, key=lambda el: el["name"]))
    print(sorted(user, key= lambda y: y["age"]))

목록에서 이름을 보면 D, B, C 및 A로 시작합니다. 연령을 알면 55, 44, 33 및 22입니다. 첫 번째 인쇄 코드

print(sorted(user, key=lambda el: el["name"]))

결과 :

[{'name': 'Abdullah', 'age': 22}, 
{'name': 'Ben', 'age': 44}, 
{'name': 'Citrus', 'age': 33}, 
{'name': 'Dough', 'age': 55}]

key = lambda el : el [ "name"]에 의해 이름을 정렬하고 이름이 알파벳 순서로 리턴되기 때문에 이름을 정렬합니다.

두 번째 인쇄 코드

print(sorted(user, key= lambda y: y["age"]))

결과:

[{'name': 'Abdullah', 'age': 22},
 {'name': 'Citrus', 'age': 33},
 {'name': 'Ben', 'age': 44}, 
 {'name': 'Dough', 'age': 55}]

연령별로 정렬되므로 목록은 오름차순으로 반환됩니다.

이해를 돕기 위해이 코드를 사용해보십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.