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의 일반적인 동작입니다.하면 이 문제를 해결할 수 .nonlocal
의 def
s, 그나러나nonlocal
에서 사용할 수 없습니다lambda
s의
해결 방법이 있습니다(아래 참조). 하지만 이 주제를 다루는 동안에는...
경우에 따라 이 기능을 사용하여 내부의 모든 작업을 수행할 수 있습니다.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]
그럼 그냥 통과하시면 됩니다.f
filter()
정말로 필요하다면, 당신은 가치를 되찾을 수 있습니다.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
'source' 카테고리의 다른 글
Firebase 비동기 대기 스타일을 위한 클라우드 기능 (0) | 2023.07.18 |
---|---|
What does it mean to squash commits in git? (0) | 2023.07.18 |
@foo는 왜.파이썬의 세터는 나에게 맞지 않습니까? (0) | 2023.07.18 |
가져오기 오류: win32api라는 이름의 모듈이 없습니다. (0) | 2023.07.18 |
일치하는 키에서 값을 수집하여 딕트를 병합하는 방법은 무엇입니까? (0) | 2023.07.18 |