source

Python의 람다 식 내부 할당

factcode 2023. 7. 18. 22:01
반응형

Python의 람다 식 내부 할당

하나를 있는 .filter a 리고a.lambda표현.

예를 들어 입력이 다음과 같은 경우:

[Object(name=""), Object(name="fake_name"), Object(name="")]

...그러면 출력은 다음과 같아야 합니다.

[Object(name=""), Object(name="fake_name")]

에할을추수있있방까습니법이는가할에 를 추가하는 요?lambda? 예:

flag = True 
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(
    (lambda o: [flag or bool(o.name), flag = flag and bool(o.name)][0]),
    input
)

Python 3.8에 추가된 할당 연산자는 람다 식 내부의 할당을 지원합니다.이 연산자는 괄호 안에만 표시할 수 있습니다.(...)가 붙은[...]또는 브레스티드{...}구문상의 이유로 사용할 수 있습니다.예를 들어 다음과 같은 내용을 작성할 수 있습니다.

import sys
say_hello = lambda: (
    message := "Hello world",
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

Python 2에서는 목록 이해의 부작용으로 로컬 할당을 수행할 수 있었습니다.

import sys
say_hello = lambda: (
    [None for message in ["Hello world"]],
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

" 나변가변수기이때예이서제두모가사수다없니" 수 .flag가 아닌 에 있습니다.lambda의 범위.이는 이 사건과 관계가 없습니다.lambda파이썬 2의 일반적인 동작입니다.하면 이 문제를 해결할 수 .nonlocaldef s, 그나러나nonlocal에서 사용할 수 없습니다lambdas의

해결 방법이 있습니다(아래 참조). 하지만 이 주제를 다루는 동안에는...


경우에 따라 이 기능을 사용하여 내부의 모든 작업을 수행할 수 있습니다.lambda:

(lambda: [
    ['def'
        for sys in [__import__('sys')]
        for math in [__import__('math')]

        for sub in [lambda *vals: None]
        for fun in [lambda *vals: vals[-1]]

        for echo in [lambda *vals: sub(
            sys.stdout.write(u" ".join(map(unicode, vals)) + u"\n"))]

        for Cylinder in [type('Cylinder', (object,), dict(
            __init__ = lambda self, radius, height: sub(
                setattr(self, 'radius', radius),
                setattr(self, 'height', height)),

            volume = property(lambda self: fun(
                ['def' for top_area in [math.pi * self.radius ** 2]],

                self.height * top_area))))]

        for main in [lambda: sub(
            ['loop' for factor in [1, 2, 3] if sub(
                ['def'
                    for my_radius, my_height in [[10 * factor, 20 * factor]]
                    for my_cylinder in [Cylinder(my_radius, my_height)]],

                echo(u"A cylinder with a radius of %.1fcm and a height "
                     u"of %.1fcm has a volume of %.1fcm³."
                     % (my_radius, my_height, my_cylinder.volume)))])]],

    main()])()

반경 10.0cm, 높이 20.0cm의 실린더는 부피가 6283.2cm³입니다.
반경 20.0cm, 높이 40.0cm인 실린더의 부피는 50265.5cm³입니다.
반경이 30.0cm이고 높이가 60.0cm인 실린더의 부피는 169646.0cm³입니다.

제발 하지마.


...예로 . ...에 대한 수는 원래의 예로 돌아가십시오. 할당을 수행할 수는 없지만,flag외부 범위의 변수로, 함수를 사용하여 이전에 계산된 값을 수정할 수 있습니다.

를 들면, 들면를예,flag▁whose의 일 수 ..value다음을 사용하여 설정합니다.

flag = Object(value=True)
input = [Object(name=''), Object(name='fake_name'), Object(name='')] 
output = filter(lambda o: [
    flag.value or bool(o.name),
    setattr(flag, 'value', flag.value and bool(o.name))
][0], input)
[Object(name=''), Object(name='fake_name')]

만약 우리가 위의 주제에 맞추기를 원한다면, 우리는 목록 이해력을 대신 사용할 수 있습니다.setattr:

    [None for flag.value in [bool(o.name)]]

하지만, 정말로, 당신은 심각한 코드에서 항상 규칙적인 함수 정의를 사용해야 합니다.lambda외부 임무를 수행할 경우.

flag = Object(value=True)
def not_empty_except_first(o):
    result = flag.value or bool(o.name)
    flag.value = flag.value and bool(o.name)
    return result
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(not_empty_except_first, input)

당신은 정말로 상태를 유지할 수 없습니다.filter/lambda식(글로벌 네임스페이스를 남용하는 경우 제외).그러나 당신은 축적된 결과를 사용하여 비슷한 것을 성취할 수 있습니다.reduce()식:

>>> f = lambda a, b: (a.append(b) or a) if (b not in a) else a
>>> input = ["foo", u"", "bar", "", "", "x"]
>>> reduce(f, input, [])
['foo', u'', 'bar', 'x']
>>> 

물론 조건을 조금 조정할 수도 있습니다., 이경중항필지사수있만습다니도용할하터링목을복우▁use다▁also▁in를 사용할 수도 있습니다.a.count("")예를 들어 빈 문자열만 제한합니다.

말할 필요도 없이, 당신은 이것을 할 수 있지만 당신은 정말 해서는 안 됩니다.:)

마지막으로 순수 파이썬에서 무엇이든 할 수 있습니다.lambda: http://vanderwijk.info/blog/pure-lambda-calculus-python/

정定)= 에서는 )를할 수 .lambda표현, 비록 다양한 트릭을 수행하는 것이 가능하지만.setattr그리고 친구들.

그러나 문제를 해결하는 것은 실제로 매우 간단합니다.

input = [Object(name=""), Object(name="fake_name"), Object(name="")]
output = filter(
    lambda o, _seen=set():
        not (not o and o in _seen or _seen.add(o)),
    input
    )

그것이 당신에게 줄 것입니다.

[Object(Object(name=''), name='fake_name')]

보시다시피 마지막 인스턴스 대신 첫 번째 인스턴스를 빈 상태로 유지합니다.대신 마지막이 필요한 경우 목록을 다음으로 되돌립니다.filter그리고 목록이 나오는 것을 뒤집습니다.filter:

output = filter(
    lambda o, _seen=set():
        not (not o and o in _seen or _seen.add(o)),
    input[::-1]
    )[::-1]

그것이 당신에게 줄 것입니다.

[Object(name='fake_name'), Object(name='')]

한 해야 할 은, 임의의 객체와 는 그 구현되어야 입니다.__eq__그리고.__hash__여기에 설명한 바와 같이

모든 null을 제거하고 입력 크기가 변경되면 람다를 사용할 필요가 없습니다.

input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = [x for x in input if x.name]
if(len(input) != len(output)):
    output.append(Object(name=""))

업데이트:

[o for d in [{}] for o in lst if o.name != "" or d.setdefault("", o) == o]

는사용을 사용합니다.filter그리고.lambda:

flag = {}
filter(lambda o: bool(o.name) or flag.setdefault("", o) == o, lst)

이전 답변

좋아요, 필터와 람다를 계속 사용하고 있나요?

사전적인 이해력이 있는 것이 더 나을 것 같습니다.

{o.name : o for o in input}.values()

는 파이썬이 생각합니다. ▁the▁on▁i▁▁things▁that▁are▁▁the▁fact▁to▁doesn▁is▁that▁do파'▁with▁something▁similar▁got▁lambda▁a▁python생있s▁the▁it관사▁and이▁why▁reason▁that▁to▁think합니각다rehension다고이▁assignC측면을 통해 속도를 높일 수 있습니다.적어도 Guido의 에세이하나를 읽고 난 후의 나의 인상입니다.

제 생각에 이것은 또한 파이썬에서 한 가지 일을 하는 올바른 방법을 갖는 철학에도 어긋나는 것 같습니다.

TL;DR: 기능성 관용구를 사용할 때는 기능성 코드를 작성하는 것이 좋습니다.

많은 사람들이 지적했듯이 Python lamdas에서는 할당이 허용되지 않습니다.일반적으로 기능성 관용구를 사용할 때 기능적인 방식으로 생각하는 것이 더 낫습니다. 이것은 가능한 한 부작용이나 과제가 없다는 것을 의미합니다.

람다를 사용하는 함수 솔루션이 있습니다.람다를 다음에 할당했습니다.fn명확성을 위해(그리고 약간 길어졌기 때문에).

from operator import add
from itertools import ifilter, ifilterfalse
fn = lambda l, pred: add(list(ifilter(pred, iter(l))), [ifilterfalse(pred, iter(l)).next()])
objs = [Object(name=""), Object(name="fake_name"), Object(name="")]
fn(objs, lambda o: o.name != '')

또한 목록보다는 반복자들과 거래를 할 수 있습니다. 약간의 변경을 통해서 말이죠.당신은 또한 몇 가지 다른 수입품을 가지고 있습니다.

from itertools import chain, islice, ifilter, ifilterfalse
fn = lambda l, pred: chain(ifilter(pred, iter(l)), islice(ifilterfalse(pred, iter(l)), 1))

언제든지 코드를 다시 구성하여 문의 길이를 줄일 수 있습니다.

반복하는 동안 상태를 추적하는 비단조적인 방법은 생성기를 사용하는 것입니다.IITER 도구 방법은 IMHO를 이해하기가 상당히 어렵고 이것을 하기 위해 람다를 해킹하려고 하는 것은 매우 어리석습니다.시도해 보겠습니다.

def keep_last_empty(input):
    last = None
    for item in iter(input):
        if item.name: yield item
        else: last = item
    if last is not None: yield last

output = list(keep_last_empty(input))

전반적으로, 가독성은 매번 압축성을 능가합니다.

에 대신에 flag = True대신 가져오기를 수행할 수 있습니다. 그러면 기준을 충족하는 것 같습니다.

>>> from itertools import count
>>> a = ['hello', '', 'world', '', '', '', 'bob']
>>> filter(lambda L, j=count(): L or not next(j), a)
['hello', '', 'world', 'bob']

또는 필터가 다음과 같이 더 잘 작성될 수 있습니다.

>>> filter(lambda L, blank_count=count(1): L or next(blank_count) == 1, a)

또는 가져오기 없이 단순 부울의 경우:

filter(lambda L, use_blank=iter([True]): L or next(use_blank, False), a)

아니요, 람다 자체 정의 때문에 람다 내부에 할당을 넣을 수 없습니다.함수형 프로그래밍을 사용하여 작업하는 경우 값이 가변적이지 않다고 가정해야 합니다.

한 가지 해결책은 다음 코드입니다.

output = lambda l, name: [] if l==[] \
             else [ l[ 0 ] ] + output( l[1:], name ) if l[ 0 ].name == name \
             else output( l[1:], name ) if l[ 0 ].name == "" \
             else [ l[ 0 ] ] + output( l[1:], name )

를 기억하기 네임스페이스에 중 합니다.__call__이제 당신이 하려는 일에 대한 나의 모든 주의가 사라졌으므로, 우리는 당신의 질문에 대한 실제적인 대답에 도달할 수 있습니다.

호출 사이에 메모리를 확보하기 위해 람다가 필요한 경우 다음과 같이 정의할 수 있습니다.

f = lambda o, ns = {"flag":True}: [ns["flag"] or o.name, ns.__setitem__("flag", ns["flag"] and o.name)][0]

그럼 그냥 통과하시면 됩니다.ffilter()정말로 필요하다면, 당신은 가치를 되찾을 수 있습니다.flag다음을 포함합니다.

f.__defaults__[0]["flag"]

의 결과를 수정하여 전역 할 수 .globals()는 유스럽로네다의 하는 것과 할 수 .locals()로컬 네임스페이스에는 영향을 주지 않습니다.

바인딩 함수를 사용하여 유사 다중 문 람다를 사용할 수 있습니다.그런 다음 플래그에 래퍼 클래스를 사용하여 할당을 사용할 수 있습니다.

bind = lambda x, f=(lambda y: y): f(x)

class Flag(object):
    def __init__(self, value):
        self.value = value

    def set(self, value):
        self.value = value
        return value

input = [Object(name=""), Object(name="fake_name"), Object(name="")]
flag = Flag(True)
output = filter(
            lambda o: (
                bind(flag.value, lambda orig_flag_value:
                bind(flag.set(flag.value and bool(o.name)), lambda _:
                bind(orig_flag_value or bool(o.name))))),
            input)

좀 어수선한 해결책이지만, 람다에서 과제를 하는 것은 어쨌든 불법이기 때문에, 그것은 별로 중요하지 않습니다.기본 제공 기능을 사용할 수 있습니다.exec()다음 예제와 같이 람다 내부에서 할당을 실행하는 함수:

>>> val
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    val
NameError: name 'val' is not defined
>>> d = lambda: exec('val=True', globals())
>>> d()
>>> val
True

먼저, 당신은 당신의 직업에 로컬 과제를 사용할 필요가 없습니다, 단지 위의 대답을 확인하세요.

둘째, 변수 표를 얻은 다음 값을 변경하기 위해 로컬 및 글로벌을 사용하는 것은 간단합니다.

다음 샘플 코드를 확인합니다.

print [locals().__setitem__('x', 'Hillo :]'), x][-1]

환경에 글로벌 변수 추가를 변경해야 하는 경우 local()을 글로벌()로 바꾸십시오.

파이썬의 리스트 컴프는 멋지지만 대부분의 전통적인 프로젝트는 이것을 받아들이지 않습니다(플라스크처럼 :[).

도움이 되기를 바랍니다

언급URL : https://stackoverflow.com/questions/6282042/assignment-inside-lambda-expression-in-python

반응형