Нові структури даних в Python 3

3 хв. читання

Люди активно переходять на Python 3, активно знайомляться з новими фічами. Про одні з таких фіч ми розповімо сьогодні: про нові типи даних.

Ми розглянемо typing.NamedTuple, types.MappingProxyType та types.SimpleNamespace. Всі вони були додані в третій версії.

typing.NamedTuple

Можна сказати, що це прокачана версія collections.namedtuple, яку додали в Python 3.5.

В чому ж він краще за відомий аналог?

  • Приємніший синтаксис
  • Наслідування
  • Анотації типів
  • Значення за умовчуванням (python >= 3.6.1)

В той же час, швидкість роботи не поступається collections.namedtuple. Розглянемо все це на прикладі:

>>> from typing import NamedTuple
>>> class Student(NamedTuple):
>>>    name: str
>>>    address: str
>>>    age: int
>>>    sex: str

>>> tommy = Student(name='Tommy Johnson', address='Main street', age=22, sex='M')
>>> tommy
Student(name='Tommy Johnson', address='Main street', age=22, sex='M')

Такий спосіб створення мені подобається більше, ніж старий, заснований на функціях. Мені здається, це виглядає приємніше.

Student – це підклас tuple, тобто з ним можна робити все те ж саме, що й з кортежем.

>>> isinstance(tommy, tuple)
True
>>> tommy[0]
'Tommy Johnson'

Приклад використання значень за умовчуванням (Python >= 3.6.1):

>>> class MaleStudent(Student):
>>>    sex: str = 'M'

>>> MaleStudent(name='Tommy Johnson', address='Main street', age=22)
MaleStudent(name='Tommy Johnson', address='Main street', age=22, sex='M')

Впевнений, що скоро вона стане стандартною реалізацією namedtuple. Доки.

types.MappingProxyType

types.MappingProxyType – це словник, який доступний лише для читання (read-only), він був доданий в Python 3.3.

Ця структура може бути корисна, якщо ви передаєте свої дані у вигляді словників в функції. Деякі функції можуть змінювати сам аргумент (хоча не повинні), і саме від цього вас вбереже MappingProxyType. Такі баги в готовому коді відслідкувати досить складно.

Приклад використання:

>>> from  types import MappingProxyType
>>> data = {'a': 1, 'b':2}
>>> read_only = MappingProxyType(data)
>>> del read_only['a']
TypeError: 'mappingproxy' object does not support item deletion
>>> read_only['a'] = 3
TypeError: 'mappingproxy' object does not support item assignment

Уявіть собі ось таку дуже-дуже велику функцію з одним невеличким багом.

>>> def my_func(in_dict):
>>>    ...  # купа коду
>>>    in_dict['a'] *= 10  # ой, який неприємний баг

...
# в якійсь функції чи потоці:
>>> my_func(data)
>>> data
data = {'a': 10, 'b':2}

А якщо ви будете використовувати mappingproxy то все це закінчиться вискакуванням виключення з вказанням файлу та рядка коду:

>>> my_func(MappingProxyType(data))
TypeError: 'mappingproxy' object does not support item deletion

І зауважте, що хоч read_only і не можна змінювати, зміна data призведе до зміни і екземпляру read_only:

>>> data['a'] = 3
>>> data['c'] = 4
>>> read_only  # змінився!
mappingproxy({'a': 3, 'b': 2, 'c': 4})

Як ви бачите, read_only – лише інтерфейс до того самого словника, про це слід пам'ятати. А більше інформації ви знайдете в документації.

types.SimpleNamespace

types.SimpleNamespace — простий клас, що дозволяє створювати і видаляти його атрибути. Ще в нього гарний вивід repr. Був доданий в Python 3.3.

>>> from types import SimpleNamespace

>>> data = SimpleNamespace(a=1, b=2)
>>> data
namespace(a=1, b=2)
>>> data.c = 3
>>> data
namespace(a=1, b=2, c=3)

Я іноді використовую його як просту альтернативу словнику. Більше того, його можна унаслідувати, щоб створювати корисні класи, що будуть економити вам час в майбутньому. Доки.

>>> import random

>>> class DataBag(SimpleNamespace):
>>>    def choice(self):
>>>        items = self.__dict__.items()
>>>        return random.choice(tuple(items))

>>> data_bag = DataBag(a=1, b=2)
>>> data_bag
DataBag(a=1, b=2)
>>> data_bag.choice()
(b, 2)
Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 3.9K
Приєднався: 11 місяців тому
Коментарі (0)

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

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

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