Python의 all()-Iterable의 진실성을 확인하세요.

2023. 12. 21. 19:32python/basic

all()은 Python에서 깔끔하고 읽기 쉽고 효율적인 코드를 작성하는 데 도움이 되는 강력한 도구입니다.

  • 다음을 사용하여 iterable의 모든 항목이 진실인지 확인하십시오.
  • 다양한 반복 가능한 유형
  • 컴프리헨션 및 생성기 표현식
  • all() 및 부울 and 연산자 구별

Iterables에서 항목의 실제 값 평가

프로그래밍에서 매우 일반적인 문제는 목록이나 배열의 모든 항목이 진실인지 아닌지를 결정하는 것입니다. m

In [ ]:
def all_true(iterable):
    for item in iterable:
        if not item:
            return False
    return True
In [ ]:
bool_exps = [
    5 > 2,
    1 == 1,
    42 < 50,
]

all_true(bool_exps)
In [ ]:
objects = ["Hello!", 42, {}]

all_true(objects)

첫 번째 예에서 입력 목록에는 문자열, 숫자 및 사전을 포함한 일반 Python 개체가 포함되어 있습니다. 이 경우 사전이 비어 있고 Python에서 false로 평가되기 때문에 all_true()는 False를 반환합니다.

In [ ]:
general_expressions = [
    5 ** 2,
    42 - 3,
    int("42")
]

all_true(general_expressions)

두 번째 예에서 입력 목록에는 수학 표현식 및 함수 호출과 같은 일반적인 Python 표현식이 포함되어 있습니다. 이 경우 Python은 먼저 표현식을 평가하여 결과 값을 얻은 다음 해당 값의 진실성을 확인합니다.

In [ ]:
empty = []

all_true(empty)

세 번째 예는 all_true()의 중요한 세부정보를 강조합니다. 입력 반복 가능 항목이 비어 있으면 for 루프가 실행되지 않고 함수는 즉시 True을 반환합니다. 이 동작은 언뜻 보기에는 이상해 보일 수 있습니다. 그러나 그 뒤에 있는 논리는 입력 반복 가능 항목에 항목이 없으면 항목이 거짓인지 말할 방법이 없다는 것입니다. 따라서 함수는 True 빈 iterable을 반환합니다.

Python의 all() 시작하기

Python의 all()는 반복 가능한 항목을 줄이기 때문에 축소 또는 접기 작업을 수행한다고 말할 수 있습니다. 항목을 단일 객체로 변환합니다. 그러나 계산을 수행하기 위해 다른 함수를 인수로 사용하지 않기 때문에 고차 함수가 아닙니다.

In [ ]:
bool_exps = [
    5 > 2,
   1 == 1,
    42 < 50,
]

all(bool_exps)
In [ ]:
objects = ["Hello!", 42, {}]

all(objects)
In [ ]:
general_exps = [
    5 ** 2,
    42 - 3,
    int("42")
]

all(general_exps)
In [ ]:
empty = []

all(empty)

빈 iterable을 사용하여 all()을 호출하면 True를 얻게 됩니다. 왜냐하면 거짓 항목이 없기 때문입니다.

다음 호출을 all() 실행하여 이 표의 정보를 확인할 수 있습니다.

In [ ]:
all([True, True, True])
In [ ]:
all([False, False, False])
In [ ]:
all([False, True, True])
In [ ]:
all([])

all_true() 함수와 마찬가지로 all()도 단락 평가라고 알려진 기능을 구현합니다. . 이러한 종류의 평가는 all()이 작업의 최종 결과를 결정하자마자 반환된다는 것을 의미합니다.

In [ ]:
def is_true(value):
    print("Side effect!")
    return bool(value)

values = [0, 1]

conditions = (is_true(n) for n in values)
all(conditions)
In [ ]:
conditions = (is_true(n) for n in reversed(values))
all(conditions)

다른 반복 가능한 유형으로 all() 사용

시퀀스

In [ ]:
# With tuples
all((1, 2, 3))
In [ ]:
all((0, 1, 2, 3))
In [ ]:
all(())
In [ ]:
all(tuple())
In [ ]:
# With range objects
all(range(10))
In [ ]:
all(range(1, 11))
In [ ]:
all(range(0))

마지막 예에서 를 인수로 사용하여 range()를 호출하면 빈 객체가 반환되므로 결과는 True를 ​​제공합니다.

사전

In [ ]:
all({"gold": 1, "silver": 2, "bronze": 3})
In [ ]:
all({0: "zero", 1: "one", 2: "two"})

첫 번째 사전의 모든 키가 진실이므로 결과는 True 입니다. 두 번째 사전에서 첫 번째 키는 0이며 이는 false로 평가됩니다. 이 경우 False all()에서 돌려받게 됩니다.

In [ ]:
medals = {"gold": 1, "silver": 2, "bronze": 3}
all(medals.keys())
In [ ]:
numbers = {0: "zero", 1: "one", 2: "two"}
all(numbers.keys())
In [ ]:
monday_inventory = {"book": 2, "pencil": 5, "eraser": 1}
all(monday_inventory.values())
In [ ]:
tuesday_inventory = {"book": 2, "pencil": 3, "eraser": 0}
all(tuesday_inventory.values())

Comprehensions 및 Generator Expressions과 함께 all() 사용하기

In [ ]:
import math

def is_prime(n):
    if n <= 1:
        return False
    for i in range(2, math.isqrt(n) + 1):
        if n % i == 0:
            return False
    return True

numbers = [2, 3, 5, 7, 11]
all([is_prime(x) for x in numbers])
In [ ]:
numbers = [2, 4, 6, 8, 10]
all([is_prime(x) for x in numbers])
In [ ]:
numbers = [1, 2, 3]
all([number > 0 for number in numbers])
In [ ]:
numbers = [-2, -1, 0, 1, 2]
all([number > 0 for number in numbers])

all()과 and 부울 연산자 비교하기

In [ ]:
all([True, False])
In [ ]:
True and False

부울 값과 피연산자 반환

In [ ]:
all(["Hello!", 42, {}])
In [ ]:
"Hello!" and 42 and {}
In [ ]:
all([1, 2, 3])
In [ ]:
1 and 2 and 3
In [ ]:
all([0, 1, 2, 3])
In [ ]:
0 and 1 and 2 and 3
In [ ]:
all([5 > 2, 1 == 1])
In [ ]:
5 > 2 and 1 == 1

Short-Circuiting the Evaluation

In [ ]:
def generate_items(iterable):
    for i, item in enumerate(iterable):
        print(f"Checking item: {i}")
        yield item
In [ ]:
# Check both items to get the result
items = generate_items([True, True])
all(items)
In [ ]:
# Check the first item to get the result
items = generate_items([False, True])
all(items)
In [ ]:
# Still have a remaining item
next(items)
In [ ]:
# Check both items to get the result
items = generate_items([True, True])
next(items) and next(items)
In [ ]:
# Check the first item to get the result
items = generate_items([False, True])
next(items) and next(items)
In [ ]:
# Still have a remaining item
next(items)

all() 실행: 실제 사례 적용하기

긴 복합 조건의 가독성 향상

In [ ]:
x = 42

if isinstance(x, int) and 0 <= x <= 100 and x % 2 == 0:
    print("Valid input")
else:
    print("Invalid input")

이 조건문의 가독성을 높이려면 다음 코드와 같이 all()를 사용할 수 있습니다.

In [ ]:
x = 42

validation_conditions = (
    isinstance(x, int),
    0 <= x <= 100,
    x % 2 == 0,
)

if all(validation_conditions):
    print("Valid input")
else:
    print("Invalid input")

이 예에서 모든 유효성 검사 조건은 설명이 포함된 이름을 가진 튜플에 있습니다. 이 기술을 사용하면 추가적인 이점이 있습니다. 새로운 유효성 검사 조건을 추가해야 하는 경우 validation_conditions 튜플에 새 줄을 추가하기만 하면 됩니다.

In [ ]:
def is_integer(x):
    return isinstance(x, int)

def is_between(a=0, b=100):
    return lambda x: a <= x <= b

def is_even(x):
    return x % 2 == 0

validation_conditions = (
    is_integer,
    is_between(0, 100),
    is_even,
)

for x in (4.2, -42, 142, 43, 42):
    print(f"Is {x} valid?", end=" ")
    print(all(condition(x) for condition in validation_conditions))

숫자 값의 반복 가능 여부 확인

In [ ]:
numbers = [10, 5, 6, 4, 7, 8, 20]

# From 0 to 20 (Both included)
all(0 <= x <= 20 for x in numbers)
In [ ]:
# From 0 to 20 (Both excluded)
all(0 < x < 20 for x in numbers)
In [ ]:
# From 0 to 20 (integers only)
all(x in range(21) for x in numbers)
In [ ]:
# All greater than 0
all(x > 0 for x in numbers)

문자열 및 문자열의 반복 가능 여부 확인

In [ ]:
numbers = ["1", "2", "3.0"]

all(number.isdecimal() for number in numbers)
In [ ]:
chars = "abcxyz123"

all(char.isalnum() for char in chars)
In [ ]:
all(char.isalpha() for char in chars)
In [ ]:
all(char.isascii() for char in chars)
In [ ]:
all(char.islower() for char in chars)
In [ ]:
all(char.isnumeric() for char in chars)
In [ ]:
all(char.isprintable() for char in chars)

표 형식 데이터에서 빈 필드가 있는 행 제거

회사 직원에 대한 데이터가 포함된 CSV 파일이 있다고 가정해 보겠습니다.

CSV 파일

name,job,email
"Linda","Technical Lead",""
"Joe","Senior Web Developer","joe@example.com"
"Lara","Project Manager","lara@example.com"
"David","","david@example.com"
"Jane","Senior Python Developer","jane@example.com"

In [ ]:
import csv
from pprint import pprint

with open("employees.csv", "r") as csv_file:
    raw_data = list(csv.reader(csv_file))

# Before cleaning
pprint(raw_data)
In [ ]:
clean_data = list(filter(all, raw_data))
In [ ]:
# After cleaning
pprint(clean_data)

사용자 정의 데이터 구조 비교

In [ ]:
from collections import UserList

class ComparableList(UserList):
    def __gt__(self, threshold):
        return all(x > threshold for x in self)

numbers = ComparableList([1, 2, 3])

numbers > 0
In [ ]:
numbers > 5

Python의 zip() 함수를 부분적으로 에뮬레이션

In [ ]:
numbers = zip(["one", "two"], [1, 2])

list(numbers)
In [ ]:
def emulated_zip(*iterables):
    lists = [list(iterable) for iterable in iterables]
    while all(lists):
        yield tuple(current_list.pop(0) for current_list in lists)

numbers = emulated_zip(["one", "two"], [1, 2])

list(numbers)