Как отфильтровать объекты из списка

«Как отфильтровать объекты из списка» — вопрос из категории Python, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Python для фильтрации списков я чаще всего использую list comprehensions или функцию filter(), в зависимости от читаемости и сложности условия.

1. List Comprehension (самый частый выбор):

# Фильтрация списка словарей (например, результатов тестов)
test_results = [
    {"name": "test_login", "status": "passed", "duration": 1.2},
    {"name": "test_payment", "status": "failed", "duration": 3.5},
    {"name": "test_logout", "status": "passed", "duration": 0.8}
]

failed_tests = [test for test in test_results if test["status"] == "failed"]
# Результат: [{'name': 'test_payment', 'status': 'failed', 'duration': 3.5}]

# Фильтрация с более сложным условием
slow_passed_tests = [
    test for test in test_results 
    if test["status"] == "passed" and test["duration"] > 1.0
]

2. Функция filter() с lambda или именованной функцией:

def is_flaky(test):
    return test.get("flaky", False) and test["status"] == "failed"

flaky_tests = list(filter(is_flaky, test_results))
# Или с lambda:
long_tests = list(filter(lambda t: t["duration"] > 2.0, test_results))

3. Для работы с коллекциями объектов (например, в UI-автотестах с Page Object):

# Допустим, у нас есть список веб-элементов
from selenium.webdriver.remote.webelement import WebElement

elements: list[WebElement] = driver.find_elements(By.CLASS_NAME, "btn")
# Фильтруем только видимые и активные кнопки
visible_buttons = [
    btn for btn in elements 
    if btn.is_displayed() and btn.is_enabled()
]

Ключевые моменты:

  • Производительность: Для очень больших списков можно рассмотреть itertools.filterfalse или генераторы.
  • Читаемость: Сложную логику фильтрации лучше выносить в отдельную именованную функцию.
  • Безопасность: Всегда проверяйте наличие ключей (dict.get()) или атрибутов (hasattr()), если данные могут быть неполными.