Знайомимось з оператором walrus у Python 3.8

2 хв. читання

З релізом альфа-версії 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 (детальніше про процес встановлення тут).

Знайомимось з оператором walrus у Python 3.8
$ 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.

Знайомимось з оператором walrus у Python 3.8

Встановлення альфа-версії з pyenv install 3.8-dev

Знайомимось з оператором walrus у Python 3.8

Тепер можна використовувати 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 за посиланням.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.8K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація