programing

3.x를 사용하여 람다 매개 변수에 대한 2.x의 튜플 언팩을 시뮬레이션하려면 어떻게 해야 합니까?

yellowcard 2023. 5. 5. 08:47
반응형

3.x를 사용하여 람다 매개 변수에 대한 2.x의 튜플 언팩을 시뮬레이션하려면 어떻게 해야 합니까?

파이썬 2에서 나는 다음을 쓸 수 있습니다.

In [5]: points = [ (1,2), (2,3)]

In [6]: min(points, key=lambda (x, y): (x*x + y*y))
Out[6]: (1, 2)

그러나 이는 3.x에서 지원되지 않습니다.

  File "<stdin>", line 1
    min(points, key=lambda (x, y): (x*x + y*y))
                           ^
SyntaxError: invalid syntax

간단한 해결 방법은 전달된 튜플에 명시적으로 인덱싱하는 것입니다.

>>> 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

하지만 그 이유는lambda하며, 표만지며원하다, 넣을 수 .x, y = p그 일에 끼어들다

이 제한을 어떻게 해결할 수 있습니까?

아니요, 다른 방법이 없어요.당신이 다 커버했어요.방법은 파이썬 아이디어 메일링 목록에 이 문제를 제기하는 것이지만, 관심을 끌기 위해 거기서 많은 논쟁을 벌일 준비가 되어 있습니다.

사실, "출구가 없다"는 말을 하지 않기 위해 세 번째 방법은 매개 변수를 펼치기 위해 람다 호출을 한 단계 더 구현하는 것일 수 있지만, 이는 두 가지 제안보다 동시에 더 비효율적이고 읽기 어려울 것입니다.

min(points, key=lambda p: (lambda x,y: (x*x + y*y))(*p))

Python 3.8 업데이트

Python 3.8 릴리스 이후 PEP 572(할당 표현식)를 도구로 사용할 수 있게 되었습니다.

따라서 람다 안에서 여러 식을 실행하기 위해 트릭을 사용하는 경우 - 저는 보통 튜플을 만들고 마지막 구성 요소만 반환하면 다음을 수행할 수 있습니다.

>>> a = lambda p:(x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
>>> a((3,4))
25

이러한 종류의 코드는 완전한 기능을 갖는 것보다 더 읽기 쉽거나 실용적인 경우가 거의 없다는 것을 명심해야 합니다.여전히 사용 가능한 용도가 있습니다. 이에 대해 작동하는 다양한 한 줄기가 있는 경우point그것은 가치가 있을 수 있습니다.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/ 에 따르면 튜플 압축 풀기가 사라졌습니다.2to3다음과 같이 번역합니다.

단일 식 제한 때문에 람다에서 튜플 매개 변수를 사용하므로 이 매개 변수도 지원해야 합니다.이 작업은 예상 시퀀스 인수를 단일 매개 변수에 바인딩한 다음 해당 매개 변수에 인덱싱함으로써 수행됩니다.

lambda (x, y): x + y

다음으로 변환됩니다.

lambda x_y: x_y[0] + x_y[1]

이는 귀사의 구현과 상당히 유사합니다.

저는 Python 2 인수 언팩 동작에 대한 좋은 일반적인 대안을 모릅니다.다음은 경우에 따라 유용할 수 있는 몇 가지 제안 사항입니다.

  • 이름이 생각나지 않는 경우 키워드 매개 변수의 이름을 사용합니다.

    def key(p): # more specific name would be better
        x, y = p
        return x**2 + y**3
    
    result = min(points, key=key)
    
  • 당신은 볼 수 있습니다.namedtuple목록이 여러 위치에서 사용되는 경우 코드를 보다 쉽게 읽을 수 있습니다.

    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에서 destructuring 인수가 제거되었지만, 이해에서 제거되지 않았습니다.이를 악용하여 Python 3에서 유사한 동작을 얻을 수 있습니다.

예:

points = [(1,2), (2,3)]
print(min(points, key=lambda y: next(x*x + y*y for (x,y) in [y])))

래퍼를 사용하는 것에 대한 허용된 답변과 비교하여, 이 솔루션은 래퍼가 첫 번째 레벨만 파괴하는 동안 인수를 완전히 구조화할 수 있습니다.즉, 할 수 있습니다.

values = [(('A',1),'a'), (('B',0),'b')]
print(min(values, key=lambda y: next(b for ((a,b),c) in (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])))

이는 수행할 수 있으며 권장 사항으로 간주해서는 안 된다는 것을 제안하기 위한 것입니다.하지만 IMO, 이것은 튜플에 여러 개의 표현을 사용하고 마지막 표현을 반환하는 해킹보다 낫습니다.

좋은 은 제생에더나것같다습니은각▁is라고 합니다.x * x + y * y let x, y = point,let키워드를 더 신중하게 선택해야 합니다.

이중 람다가 가장 가까운 버전입니다. lambda point: (lambda x, y: x * x + y * y)(*point)

고차 함수 도우미는 적절한 이름을 부여할 경우 유용할 것입니다.

def destruct_tuple(f):
  return lambda args: f(*args)

destruct_tuple(lambda x, y: x * x + y * y)

태플의 압축을 풀 필요가 있는지 여부를 먼저 고려합니다.

min(points, key=lambda p: sum(x**2 for x in p))

또는 포장을 풀 때 명시적인 이름을 제공해야 하는지 여부:

min(points, key=lambda p: abs(complex(*p)**2)

이해관계에 풀기에 대한 의 의견을 은 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]

PyFunctional을 사용하면 이에 대한 진정한 해결책이 있을 수 있습니다!

현재 지원되지는 않지만 다음을 지원하기 위해 Tuplearg 압축 풀기 기능 요청을 제출했습니다.

(
    seq((1, 2), (3, 4))
    .map(unpack=lambda a, b: a + b)
)  # => [3, 7]

스택 오버플로에 대한 질문은 질문에 답변을 포함하지 않아야 하며 명시적인 "업데이트" 섹션이 없어야 하므로 OP의 원래 "업데이트"를 적절한 답변으로 변환하여 커뮤니티 위키로 만들고 있습니다.

OP는 원래 이 솔루션이 "답안의 아이디어를 확장하는 것"이라고 주장했습니다.나는 그것이 어떤 대답을 의미하는지, 어떤 생각을 의미하는지 분간할 수 없습니다.이 아이디어는 앤서니와 기능적으로 동일합니다.hl의 대답, 하지만 그것은 몇 년 후에 나왔습니다.당시 답변 상태를 고려하면 OP의 오리지널 작품으로 손색이 없다고 생각합니다.)


다음과 같이 인수의 압축을 푸는 과정을 일반화하는 래퍼 함수를 만듭니다.

def star(f):
    return lambda args: f(*args)

이제 우리는 이것을 사용하여 쓸 람다를 인수를 적절하게 수신할 수 있는 람다로 변환할 수 있습니다.

min(points, key=star(lambda x,y: (x*x + y*y))

우리는 funtool을 사용하여 이것을 더 정리할 수 있습니다.:

import functools

def star(f):
    @functools.wraps(f)
    def f_inner(args):
        return f(*args)
    return f_inner

언급URL : https://stackoverflow.com/questions/21892989/how-can-i-simulate-2-xs-tuple-unpacking-for-lambda-parameters-using-3-x

반응형