Можно ли данный код сократить до одной строчки

sku_ = re.search("Артикул товара: (\d+)", item_info.text)
sku = sku_[1] if sku_ else ""

Можно ли данный код сократить до одной строчки?


Ответы (4 шт):

Автор решения: CrazyElf

У меня так получилось, но наверняка можно ещё лучше сделать:

sku = (re.search("Артикул товара: (\d+)", item_info.text) or ('',''))[1]
→ Ссылка
Автор решения: Alexey Shmelev

Мой вариант

sku = sku[1] if (sku := re.search("Артикул товара:(\d+);", item_info)) else ''
→ Ссылка
Автор решения: insolor

Вариант решения через контейнер Maybe из библиотеки dry-python/returns

import re

from returns.maybe import Maybe


def get_sku(text):
    return (
        Maybe.from_optional(re.search("Артикул товара: (\d+)", text))
        .bind_optional(lambda x: x[1])  # Или .bind_optional(itemgetter(1))
        .value_or("")
    )


assert get_sku("Артикул товара: 12323423") == "12323423"
assert get_sku("sdfwefew") == ""

Это похоже на класс Optional из Java, но названия методов совершенно другие, и по ним сразу не угадаешь что делает каждый метод.

На Java выглядело бы примерно так:

// Псевдокод
sku = Optional.ofNullable(re.search("Артикул товара: (\d+)", text))
    .map(lambda x: x[1])
    .orElse("");

Тут довольно очевидно, что map применяет функцию к непустому результату, но что делает bind_optional глядя на код так просто не угадаешь.

Так что скорее не рекомендую такой способ.

→ Ссылка
Автор решения: Stanislav Volodarskiy

Кое-кто считает оператор := некрасивым. Кто-то полагает что оператор or нехорошо применять к не булевым значениям. Обойдёмся без некрасивых и нехороших вещей с помощью лямбды:

sku = (lambda m: m[1] if m else "")(re.search("Артикул товара: (\d+)", item_info.text))

P.S. Это шутка. Определённая и сразу вызванная лямбда - такой же или худший костыль как := или or.

P.P.S. Механизм наподобие этого позволяет записать в одну строку вообще любое вычисление (исключения, асинхронность и т.п. отложим пока в сторону).

→ Ссылка