Люди активно переходять на 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)
Ще немає коментарів