Можно ли данный код сократить до одной строчки
sku_ = re.search("Артикул товара: (\d+)", item_info.text)
sku = sku_[1] if sku_ else ""
Можно ли данный код сократить до одной строчки?
Ответы (4 шт):
У меня так получилось, но наверняка можно ещё лучше сделать:
sku = (re.search("Артикул товара: (\d+)", item_info.text) or ('',''))[1]
Мой вариант
sku = sku[1] if (sku := re.search("Артикул товара:(\d+);", item_info)) else ''
Вариант решения через контейнер 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 глядя на код так просто не угадаешь.
Так что скорее не рекомендую такой способ.
Кое-кто считает оператор := некрасивым. Кто-то полагает что оператор or нехорошо применять к не булевым значениям. Обойдёмся без некрасивых и нехороших вещей с помощью лямбды:
sku = (lambda m: m[1] if m else "")(re.search("Артикул товара: (\d+)", item_info.text))
P.S. Это шутка. Определённая и сразу вызванная лямбда - такой же или худший костыль как := или or.
P.P.S. Механизм наподобие этого позволяет записать в одну строку вообще любое вычисление (исключения, асинхронность и т.п. отложим пока в сторону).