여기서는 "리스트를 만들까?"보다 질문 결과가 bool 하나인지, 만족한 항목 자체가 필요한지를 먼저 봅니다.
하나라도 맞는지, 모두 맞는지, 첫 일치 항목을 꺼내야 하는지에 따라 any(), all(), next()가 갈립니다.
빠른 비교
has_error = any(line.startswith("ERROR") for line in lines)
all_ready = all(task.done for task in tasks)
first_admin = next((user for user in users if user["role"] == "admin"), None)문법
기본형은 truthy/falsy 검사, 조건식 순회, 첫 항목 추출까지 같이 보면 됩니다.
any(iterable)
all(iterable)
any(cond(x) for x in items)
all(cond(x) for x in items)
next((x for x in items if cond(x)), default)any()와 all()은 iterable 안의 각 값을 truthy/falsy로 읽습니다.
이미 True/False 값이 있으면 그대로 넘기고, 조건 비교가 필요하면 generator expression으로 감싸는 식이 가장 흔합니다.
질문 종류
하나라도 맞는가, 모두 맞는가를 먼저 고른다
하나라도 참이면 끝나는 질문은 any(), 전부 참이어야 하는 질문은 all()이 맞습니다.
flags = [False, False, True]
has_true = any(flags)이미 bool 값 목록이 있다면 그대로 넘기면 됩니다.
all_passed = all(score >= 60 for score in scores)
has_admin = any(user["role"] == "admin" for user in users)이처럼 조건 비교가 필요한 순간에만 generator expression을 붙이면 코드 의도가 가장 직접적으로 읽힙니다.
평가 방식
generator expression을 바로 넘기면 중간 리스트를 만들지 않는다
any()와 all()은 iterable을 앞에서부터 읽다가 답이 정해지면 멈춥니다.
그래서 결과가 bool 하나일 때는 보통 리스트 컴프리헨션보다 generator expression이 더 잘 맞습니다.
has_error = any(line.startswith("ERROR") for line in lines)
all_valid = all(item.is_valid() for item in items)질문 하나에 답하는 용도라면 flag = False를 두고 루프 안에서 바꾸는 패턴보다 이쪽이 더 짧고 덜 흔들립니다.
결과 선택
bool이 필요하면 any()와 all(), 항목이 필요하면 next()로 간다
any()와 all()은 질문에 대한 답만 줍니다.
어떤 값이 조건을 만족했는지 그 항목 자체가 필요하면 next()나 일반 루프가 더 적합합니다.
first_admin = next((user for user in users if user["role"] == "admin"), None)후속 처리까지 길어지거나, 일치한 모든 항목을 모아야 하거나, 중간에 로그를 남겨야 하면 결국 명시적인 for 루프가 더 읽기 쉽습니다.
주의할 점
any([ ... ]), all([ ... ])처럼 리스트를 먼저 만들면 메모리를 더 쓰고, 질문형 코드의 장점도 약해집니다.
# ❌ 중간 리스트를 먼저 만듦
has_error = any([line.startswith("ERROR") for line in lines])
# ✅ 바로 iterable로 전달
has_error = any(line.startswith("ERROR") for line in lines)
# ✅ 항목 자체가 필요하면 next()로 방향을 바꾼다
first_error = next((line for line in lines if line.startswith("ERROR")), None)참고 링크
2 sources