З релізом альфа-версії Python 3.8 ми отримали нову фічу — PEP 572 (вирази присвоєння).
Що таке оператор walrus
?
walrus-оператор — альтернативна назва для виразів присвоєння.
У більшості випадків, коли можна використати довільні вирази Python, ми зустрічаємо іменовані вирази. Вони виглядають таким чином: Назва := вираз
, де вираз
являє собою будь-який допустимий вираз у Python, окрім unparenthesized tuple
, а NAME
— ідентифікатор.
Значення такого іменованого виразу збігається зі значенням включеного виразу з додатковим побічним ефектом, що націлений на присвоєння цього значення.
# Джерело: https://www.python.org/dev/peps/pep-0572/#syntax-and-semantics
# Шукаємо відповідності регулярному виразу
if (match := pattern.search(data)) is not None:
# Обробляємо знайдені відповідності
# Цикл, який не можна просто переписати, використовуючи iter() з 2 аргументами
while chunk := file.read(8192):
process(chunk)
# Повторно використовуємо значення, яке «дорого» обчислювати
[y := f(x), y**2, y**3]
# Розділяємо підвираз на спискове включення та його результат
filtered_data = [y for x in data if (y := f(x)) is not None]
Розглянемо як можна використати новий оператор на реальних прикладах.
Для початку треба встановити Python 3.8. Щоб швидко перемикатися між версіями, можна використати pyenv (детальніше про процес встановлення тут).
$ brew update
$ brew install pyenv
На цьому етапі виконуємо pyenv init
та слідуємо інструкціям.
Встановимо python 3.8-dev з pyenv та налаштуємо наше середовище на використання цієї версії (як альтернативу pyenv можна використовувати pipenv). Але спершу слід встановити та налаштувати zlib, щоб уникнути такої помилки:
$ pyenv install 3.8-dev
python-build: use openssl from homebrew
python-build: use readline from homebrew
Cloning https://github.com/python/cpython...
Installing Python-3.8-dev...
python-build: use readline from homebrew
BUILD FAILED (OS X 10.14.2 using python-build 20180424)
Inspect or clean up the working tree at /var/folders/bj/zvdqzwk110gcrvtbw17wv1c80000gn/T/python-build.20190207152040.86672
Results logged to /var/folders/bj/zvdqzwk110gcrvtbw17wv1c80000gn/T/python-build.20190207152040.86672.log
Last 10 log lines:
return _bootstrap(
File "/private/var/folders/bj/zvdqzwk110gcrvtbw17wv1c80000gn/T/python-build.20190207152040.86672/Python-3.8-dev/Lib/ensurepip/__init__.py", line 117, in _bootstrap
return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
File "/private/var/folders/bj/zvdqzwk110gcrvtbw17wv1c80000gn/T/python-build.20190207152040.86672/Python-3.8-dev/Lib/ensurepip/__init__.py", line 27, in _run_pip
import pip._internal
File "<frozen zipimport>", line 241, in load_module
File "<frozen zipimport>", line 709, in _get_module_code
File "<frozen zipimport>", line 570, in _get_data
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
На щастя, це легко виправити.
# Встановлення zlib
brew install zlib
# Додаємо змінні zlib до середовища
tee -a ~/.profile <<<CONF
export PKG_CONFIG_PATH="/usr/local/opt/zlib/lib/pkgconfig"
export LDFLAGS="-L/usr/local/opt/zlib/lib"
export CPPFLAGS="-I/usr/local/opt/zlib/include"
CONF
# Перезавантажуємо
trap $SHELL EXIT && exit
Тепер можна легко встановити python 3.8, використовуючи pyenv.
Встановлення альфа-версії з pyenv install 3.8-dev
Тепер можна використовувати Python 3.8, запустивши pyenv shell 3.8-dev
Victor Stinner, розробник Python Core, наочно продемонстрував використання нового walrus-оператора в стандартій бібліотеці Python.
Спробуймо оператор в дії. Для порівняння напишемо фрагмент коду, використовуючи синтаксис pre-3.8 та реалізуємо те ж саме з оператором walrus
. Для нашого прикладу візьмемо набір тестових даних з jsonplaceholder, перевіряємо чи існує властивість, а потім виводимо її.
sample_data = [
{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": False},
{"userId": 1, "id": 2, "title": "quis ut nam facilis", "completed": False},
{"userId": 1, "id": 3, "title": "fugiat veniam minus", "completed": False},
{"userId": 1, "id": 4, "title": "et porro tempora", "completed": True},
{"userId": 1, "id": 4, "title": None, "completed": True},
]
print("With Python 3.8 Walrus Operator:")
for entry in sample_data:
if title := entry.get("title"):
print(f'Found title: "{title}"')
print("Without Walrus operator:")
for entry in sample_data:
title = entry.get("title")
if title:
print(f'Found title: "{title}"')
Результат:
$ python --version; python walrus.py
Python 3.8.0a1+
With Python 3.8 Walrus Operator:
Found title: "delectus aut autem"
Found title: "quis ut nam facilis"
Found title: "fugiat veniam minus"
Found title: "et porro tempora"
Without Walrus operator:
Found title: "delectus aut autem"
Found title: "quis ut nam facilis"
Found title: "fugiat veniam minus"
Found title: "et porro tempora"
Як бачимо, з warlus-оператором усе працює відмінно.
Більше інформації та прикладів шукайте в офіційному PEP, а детальніше про фічі нового релізу python 3.8.0a1 за посиланням.
Ще немає коментарів