[python] 부작용에 대한 목록 이해력을 사용하는 것이 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...))

이들은 생성기 표현식이며 버려지는 무작위 목록을 생성하지 않습니다. 나는 생각 all나는 그들 모두가 혼란하고 사용할 수 없습니다한다고 생각하지만 형태가 약간 아마 더 분명하다.

나는 이것이 추악하다고 생각하고 실제로 코드에서 그것을하지 않을 것입니다. 하지만 이런 방식으로 루프를 구현해야한다고 주장한다면 그렇게 할 것입니다.

나는 목록 이해력과 그들의 ilk가 적어도 기능적 스타일과 약간 닮은 것을 사용하려는 시도를 나타내야한다고 생각하는 경향이 있습니다. 그 가정을 깨뜨리는 부작용이있는 것을 넣으면 사람들이 당신의 코드를 더주의 깊게 읽어야하는데, 그것은 나쁜 것이라고 생각합니다.