development

부작용에 대한 목록 이해력을 사용하는 것이 Pythonic입니까?

big-blog 2020. 8. 25. 20:06
반응형

부작용에 대한 목록 이해력을 사용하는 것이 Pythonic입니까?


반환 값이 아닌 부작용 (화면에 인쇄, GUI 업데이트, 파일로 인쇄 등)이 아닌 부작용으로 호출하는 함수를 생각해보십시오.

def fun_with_side_effects(x):
    ...side effects...
    return y

이제이 func를 호출하기 위해 목록 이해력을 사용하는 것이 Pythonic입니까 ?

[fun_with_side_effects(x) for x in y if (...conditions...)]

목록을 어디에도 저장하지 않습니다.

또는이 func를 다음과 같이 호출해야합니다.

for x in y:
    if (...conditions...):
        fun_with_side_effects(x)

어느 것이 더 낫고 그 이유는 무엇입니까?


그렇게하는 것은 매우 반 파이 토닉이며 노련한 Pythonista는 당신에게 지옥을 줄 것입니다. 중간 목록은 생성 된 후 버려 지므로 잠재적으로 매우 크고 생성 비용이 많이들 수 있습니다.


사람들이 말했듯이 필요하지 않은 큰 임시 목록을 만들 것이기 ​​때문에 목록 이해력을 사용해서는 안됩니다 . 다음 두 가지 방법은 동일합니다.

consume(side_effects(x) for x in xs)

for x in xs:
    side_effects(x)

man 페이지 consume에서 정의 itertools:

def consume(iterator, n=None):
    "Advance the iterator n-steps ahead. If n is none, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

물론 후자는 더 명확하고 이해하기 쉽습니다.


목록 이해는 목록을 만드는 데 사용됩니다. 그리고 실제로 목록을 작성하지 않는 한 목록 이해를 사용 해서는 안됩니다 .

그래서 두 번째 옵션을 얻었습니다. 목록을 반복 한 다음 조건이 적용될 때 함수를 호출합니다.


두 번째가 더 좋습니다.

코드를 이해해야하는 사람을 생각해보십시오. 첫 번째로 쉽게 업장을 얻을 수 있습니다 :)

filter ()를 사용하여 둘 사이의 중간에 갈 수 있습니다. 예를 고려하십시오.

y=[1,2,3,4,5,6]
def func(x):
    print "call with %r"%x

for x in filter(lambda x: x>3, y):
    func(x)

목표에 따라 다릅니다.

목록의 각 개체에 대해 몇 가지 작업을 수행하려는 경우 두 번째 방법을 채택해야합니다.

다른 목록에서 목록을 생성하려는 경우 목록 이해를 사용할 수 있습니다.

명시적인 것이 암시적인 것보다 낫습니다. 단순한 것이 복잡한 것보다 낫습니다. (파이썬 젠)


넌 할 수있어

for z in (fun_with_side_effects(x) for x in y if (...conditions...)): pass

하지만 그다지 예쁘지 않습니다.


부작용에 대한 목록 이해력을 사용하는 것은 추악하고 비파이 토닉이며 비효율적이며 저는 그렇게하지 않을 것입니다. for루프 for는 부작용이 중요한 절차 적 스타일을 나타 내기 때문에 대신 루프를 사용합니다 .

그러나 부작용에 대한 목록 이해를 절대적으로 사용해야한다면 생성기 표현식을 대신 사용하여 비 효율성을 피해야합니다. 이 스타일을 절대적으로 고집한다면 다음 두 가지 중 하나를 수행하십시오.

any(fun_with_side_effects(x) and False for x in y if (...conditions...))

또는:

all(fun_with_side_effects(x) or True for x in y if (...conditions...))

These are generator expressions, and they do not generate a random list that gets tossed out. I think the all form is perhaps slightly more clear, though I think both of them are confusing and shouldn't be used.

I think this is ugly and I wouldn't actually do it in code. But if you insist on implementing your loops in this fashion, that's how I would do it.

I tend to feel that list comprehensions and their ilk should signal an attempt to use something at least faintly resembling a functional style. Putting things with side effects that break that assumption will cause people to have to read your code more carefully, and I think that's a bad thing.

참고URL : https://stackoverflow.com/questions/5753597/is-it-pythonic-to-use-list-comprehensions-for-just-side-effects

반응형