다음 python2 코드를 고려하십시오.
In [5]: points = [ (1,2), (2,3)]
In [6]: min(points, key=lambda (x, y): (x*x + y*y))
Out[6]: (1, 2)
이것은 python3에서 지원되지 않으며 다음을 수행해야합니다.
>>> min(points, key=lambda p: p[0]*p[0] + p[1]*p[1])
(1, 2)
이것은 매우 추합니다. 람다가 함수라면 할 수 있습니다.
def some_name_to_think_of(p):
x, y = p
return x*x + y*y
python3에서이 기능을 제거하면 코드가 추악한 방식 (매직 인덱스 사용)을 수행하거나 불필요한 함수를 생성합니다 (가장 귀찮은 부분은 이러한 불필요한 함수에 대한 좋은 이름을 생각하는 것입니다).
이 기능은 적어도 람다에만 다시 추가되어야한다고 생각합니다. 좋은 대안이 있습니까?
업데이트 : 답변에서 아이디어를 확장하는 다음 도우미를 사용하고 있습니다.
def star(f):
return lambda args: f(*args)
min(points, key=star(lambda x,y: (x*x + y*y))
Update2 : 더 깨끗한 버전star
import functools
def star(f):
@functools.wraps(f):
def f_inner(args):
return f(*args)
return f_inner
답변
아니, 다른 방법은 없습니다. 당신은 모든 것을 다뤘습니다. 갈 길은이 문제를 파이썬 아이디어 메일 링리스트 에 올리는 것입니다 .하지만 거기에서 관심을 끌기 위해 많은 논쟁을 할 준비를하세요.
사실, “출구가 없다”라고 말하지 않고, 세 번째 방법은 매개 변수를 펼치기 위해 하나 이상의 람다 호출 수준을 구현하는 것입니다.하지만 이는 두 가지 제안보다 비효율적이고 읽기 어렵습니다.
min(points, key=lambda p: (lambda x,y: (x*x + y*y))(*p))
Python 3.8 업데이트
현재 Python 3.8 alpha1을 사용할 수 있으며 PEP 572- 할당 표현식이 구현되었습니다.
따라서 트릭을 사용하여 람다 내에서 여러 표현식을 실행하면 일반적으로 튜플을 만들고 마지막 구성 요소 만 반환하여 수행 할 수 있습니다.
>>> a = lambda p:(x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
>>> a((3,4))
25
이런 종류의 코드는 완전한 기능을 갖는 것보다 더 읽기 쉽고 실용적이지 않다는 것을 명심해야합니다. 여전히 가능한 사용이 있습니다. 만약 이것에 대해 작동 할 다양한 one- point
liners가 있다면 namedtuple을 가지고 할당 표현식을 사용하여 들어오는 시퀀스를 namedtuple로 효과적으로 “캐스트”하는 것이 좋습니다.
>>> from collections import namedtuple
>>> point = namedtuple("point", "x y")
>>> b = lambda s: (p:=point(*s), p.x ** 2 + p.y ** 2)[-1]
답변
http://www.python.org/dev/peps/pep-3113/ 에 따르면 tuple unpacking이 사라지고 2to3
다음과 같이 번역됩니다.
튜플 매개 변수는 단일 식 제한으로 인해 람다에서 사용되므로 지원해야합니다. 이는 예상되는 시퀀스 인수를 단일 매개 변수에 바인드 한 다음 해당 매개 변수를 인덱싱하여 수행됩니다.
lambda (x, y): x + y
다음으로 번역됩니다.
lambda x_y: x_y[0] + x_y[1]
귀하의 구현과 매우 유사합니다.
답변
파이썬 2 인수 압축 해제 동작에 대한 좋은 일반적인 대안을 모릅니다. 다음은 경우에 따라 유용 할 수있는 몇 가지 제안입니다.
-
이름이 생각 나지 않는다면 키워드 매개 변수의 이름을 사용하십시오.
def key(p): # more specific name would be better x, y = p return x**2 + y**3 result = min(points, key=key)
-
namedtuple
목록이 여러 위치에서 사용되는 경우 a 가 코드를 더 읽기 쉽게 만드는지 확인할 수 있습니다.from collections import namedtuple from itertools import starmap points = [ (1,2), (2,3)] Point = namedtuple('Point', 'x y') points = list(starmap(Point, points)) result = min(points, key=lambda p: p.x**2 + p.y**3)
답변
비 구조화 인수는 Python3에서 제거되었지만 이해에서 제거되지 않았습니다. 파이썬 3에서 유사한 동작을 얻기 위해 그것을 남용 할 수 있습니다. 본질적으로, 우리는 코 루틴이 우리가 함수를 뒤집을 수 있도록 허용하고 yield는 진술이 아니므로 람다 내에서 허용된다는 사실을 이용합니다.
예를 들면 :
points = [(1,2), (2,3)]
print(min(points, key=lambda y: next(x*x + y*y for x,y in (lambda a: (yield a))(y))))
래퍼 사용에 대한 허용 된 답변과 비교하여이 솔루션은 인수를 완전히 분해 할 수있는 반면 래퍼는 첫 번째 수준 만 분해합니다. 그건,
values = [(('A',1),'a'), (('B',0),'b')]
print(min(values, key=lambda y: next(b for (a,b),c in (lambda x: (yield x))(y))))
비교해서
values = [(('A',1),'a'), (('B',0),'b')]
print(min(points, key=lambda p: (lambda a,b: (lambda x,y: (y))(*a))(*p)))
또는 하나도 할 수 있습니다
values = [(('A',1),'a'), (('B',0),'b')]
print(min(points, key=lambda y: next(b for (a,b),c in [y])))
또는 약간 더
print(min(values, key=lambda y: next(b for ((a,b),c) in (y,))))
이것은 단지 할 수 있다는 것을 암시하기위한 것이며 권장 사항으로 받아 들여서는 안됩니다.
답변
Cuadue 제안과 압축 풀기에 대한 귀하의 의견을 바탕으로 여전히 이해하기 위해 다음을 사용할 수 있습니다 numpy.argmin
.
result = points[numpy.argmin(x*x + y*y for x, y in points)]
답변
또 다른 옵션은 키가 첫 번째 요소 인 튜플을 생성하는 생성기에 작성하는 것입니다. 튜플은 처음부터 끝까지 비교되므로 첫 번째 요소가 가장 작은 튜플이 반환됩니다. 그런 다음 결과를 색인화하여 값을 얻을 수 있습니다.
min((x * x + y * y, (x, y)) for x, y in points)[1]
답변
처음에 튜플을 풀어야하는지 고려하십시오.
min(points, key=lambda p: sum(x**2 for x in p))
또는 압축을 풀 때 명시적인 이름을 제공해야하는지 여부 :
min(points, key=lambda p: abs(complex(*p))
