Меню Закрити

Фічі Python 3, про які варто знати

Розповідає Vinko Kodžoman

Багато людей почали оновлювати свої проекти до третьої версії Python після виходу Python EOL. На жаль, основна частина коду на Python 3, як на мене, мало відрізняється від Python 2, оскільки розробники не завжди знають, на що здатен третій Python. Далі я покажу кілька прикладів цікавих функцій, які можна використовувати тільки в Python 3.

Усі приклади написано на Python 3.7, і для кожної функції зазначено мінімально необхідну версію Python.

f-рядки (3.6+)

Важко що-небудь робити без рядків у будь-якій мові програмування, а задля повноцінної роботи потрібно мати структурований спосіб обробки рядків. Більшість людей, які користуються Python, воліють використовувати метод format.

user = "Jane Doe"
action = "buy"
log_message = 'User {} has logged in and did an action {}.'.format(
  user,
  action
)
print(log_message)
# User Jane Doe has logged in and did an action buy.

Поряд із format Python 3 пропонує гнучкий спосіб виконання рядкової інтерполяції за допомогою f-рядків. Тепер погляньте на той самий код, але створений за допомогою f-рядків:

user = "Jane Doe"
action = "buy"
log_message = f'User {user} has logged in and did an action {action}.'
print(log_message)
# User Jane Doe has logged in and did an action buy.

Pathlib (3.4+)

f-рядки дивовижні, але деякі рядки, такі як шляхи до файлів, мають свої власні бібліотеки, які роблять маніпуляції з ними ще простішими. Python 3 пропонує pathlib як зручну абстракцію для роботи зі шляхами файлів. Якщо не впевнені, чи треба вам використовувати pathlib, спробуйте прочитати цей чудовий пост — Чому вам варто використовувати pathlib від Trey Hunner.

from pathlib import Path
root = Path('post_sub_folder')
print(root)
# post_sub_folder
path = root / 'happy_user'
# Make the path absolute
print(path.resolve())
# /home/weenkus/Workspace/Projects/DataWhatNow-Codes/how_your_python3_should_look_like/post_sub_folder/happy_user

Анотації (3.5+)

Статичне чи динамічна типізація є гострою темою в розробці програмного забезпечення, і майже кожен має свою думку. Я залишаю читачам право вирішити, чи потрібна їм статична типізація, але я думаю, ви повинні хоча б знати, що Python 3 підтримує анотації.

def sentence_has_animal(sentence: str) -> bool:
  return "animal" in sentence
sentence_has_animal("Donald had a farm without animals")
# True

Перелічення (enumerations) (3.4+)

Python 3 підтримує простий спосіб написання перелічень за допомогою класу Enum. Enum є зручним способом інкапсуляції константних списків, щоб вони не були розкидані по всьому коду без структури.

from enum import Enum, auto
class Monster(Enum):
    ZOMBIE = auto()
    WARRIOR = auto()
    BEAR = auto()
    
print(Monster.ZOMBIE)
# Monster.ZOMBIE

Перелічення —  набір символічних імен (членів), прив’язаних до унікальних, постійних значень. У переліченні члени можна порівнювати, а сам перелік є ітерованим.

Деталі тут.

for monster in Monster:
    print(monster)
# Monster.ZOMBIE
# Monster.WARRIOR
# Monster.BEAR

Вбудований кеш LRU (3.2+)

Кеші є практично в будь-якому горизонтальному фрагменті програмного й апаратного забезпечення, яке нині використовується. Python 3 робить їх дуже простими, виставляючи LRU (Least Recently Used) (останній за часом використання) кеш як декоратор під назвою lru_cache.

Нижче наведено просту функцію Фібоначчі, що, як відомо, виграє від кешування, оскільки вона виконує ту саму роботу кілька разів шляхом рекурсії.

import time
def fib(number: int) -> int:
    if number == 0: return 0
    if number == 1: return 1
    
    return fib(number-1) + fib(number-2)
start = time.time()
fib(40)
print(f'Duration: {time.time() - start}s')
# Duration: 30.684099674224854s

Тепер ми можемо використовувати lru_cache для його оптимізації (ця методика оптимізації називається мемоізацією). Час виконання скорочується від секунд до наносекунд.

from functools import lru_cache
@lru_cache(maxsize=512)
def fib_memoization(number: int) -> int:
    if number == 0: return 0
    if number == 1: return 1
    
    return fib_memoization(number-1) + fib_memoization(number-2)
start = time.time()
fib_memoization(40)
print(f'Duration: {time.time() - start}s')
# Duration: 6.866455078125e-05s

Розширене ітероване розпакування (3.0+)

Нехай код говорить сам за себе (документація).

head, *body, tail = range(5)
print(head, body, tail)
# 0 [1, 2, 3] 4
py, filename, *cmds = "python3.7 script.py -n 5 -l 15".split()
print(py)
print(filename)
print(cmds)
# python3.7
# script.py
# ['-n', '5', '-l', '15']
first, _, third, *_ = range(10)
print(first, third)
# 0 2

Класи даних (3.7+)

Python 3 вводить класи даних, які не мають багатьох обмежень і можуть використовуватися для зменшення шаблонного коду, оскільки декоратор автоматично генерує спеціальні методи, такі як __init __ () і __repr () _. У документації вони описуються як “змінні назви кортежів зі значенням за замовчуванням”.

class Armor:
    
    def __init__(self, armor: float, description: str, level: int = 1):
        self.armor = armor
        self.level = level
        self.description = description
                 
    def power(self) -> float:
        return self.armor * self.level
    
armor = Armor(5.2, "Common armor.", 2)
armor.power()
# 10.4
print(armor)
# <__main__.Armor object at 0x7fc4800e2cf8>

Така сама реалізація класу Armor за допомогою класів даних.

from dataclasses import dataclass
@dataclass
class Armor:
    armor: float
    description: str
    level: int = 1
    
    def power(self) -> float:
        return self.armor * self.level
    
armor = Armor(5.2, "Common armor.", 2)
armor.power()
# 10.4
print(armor)
# Armor(armor=5.2, description='Common armor.', level=2)

Неявні пакети простору імен (3.3+)

Один із способів структурування коду Python полягає в пакетах (директорії із файлом __init__.py). Нижче наведу приклад з офіційної документації Python.

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

У Python 2 у кожній зазначені вище директорії повинен бути файл __init__.py, який перетворює цю директорію на пакет Python. У Python 3, із введенням неявних пакетів простору імен , ці файли більше не потрібні.

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              equalizer.py
              vocoder.py
              karaoke.py
              ...

Але усе не так просто. Згідно з офіційною специфікацією PEP 420  файли __init__.py все ще потрібні для звичайних пакетів. Якщо викинути цей файл зі структури каталогу, він перетвориться на оригінальний пакет простору імен, який має додаткові обмеження; офіційна документація щодо оригінальних пакетів простору імен чудово це ілюструє, а також містить всі обмеження.

На завершення

Як майже будь-який перелік в інтернеті, цей не є вичерпним. Я сподіваюся, що цей пост показав хоча б одну фічу Python 3, про яку ви раніше не знали, і це допоможе писати більш чистий та інтуїтивний код. Як завжди, увесь код можна знайти на GitHub.

Якщо ви знайшли помилку, будь ласка, виділіть фрагмент тексту та натисніть Ctrl+Enter.

0

Повідомити про помилку

Текст, який буде надіслано нашим редакторам: