Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Жизненный цикл Python объекта

Жизненный цикл Python объекта

Алексей Кузьмин (технический руководитель, Domclick) @ MoscowPython Meetup 62

"В докладе мы рассмотрим основные этапы жизненного цикла объекта, поговорим о том, что происходит, когда он создается, когда кто-то запрашивает доступ к его атрибутам и когда он разрушается.
Доклад направлен на junior/middle-разработчиков, желающих лучше разобраться во внутренней организации Python".

Видео: http://www.moscowpython.ru/meetup/62/python-object-life-cycle/

Moscow Python Meetup
PRO

December 27, 2018
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. ЖИЗНЕННЫЙ ЦИКЛ
    PYTHON-ОБЪЕКТА
    КУЗЬМИН АЛЕКСЕЙ «ДОМКЛИК»

    View Slide

  2. ОБО МНЕ
    • Директор разработки
    • Работа с данными & DS
    • Докладчик PyCon 2017, PyCon 2018,
    MoscowPython, …
    • Не люблю гироскутеры, смузи и вот
    это все

    View Slide

  3. О КОМПАНИИ
    • Ипотека онлайн
    • Доп продукты
    • Маркетплейс недвижимости
    • Python, Asyncio, Postgresql
    • ML NLP&CV

    View Slide

  4. СОЗДАНИЕ ЭКЗЕМПЛЯРА КЛАССА
    class Number:
    def __init__(self, value):
    self.value = value
    n = Number(5)
    Простой ответ – вызывается init. Правильный ли он?

    View Slide

  5. СОЗДАНИЕ ЭКЗЕМПЛЯРА КЛАССА
    class Number:
    def __init__(self, value):
    self.value = value
    n = Number(5)
    Простой ответ – вызывается init. Правильный ли он?
    не совсем =)

    View Slide

  6. ПОГОВОРИМ НЕМНОЖКО О
    МЕТАКЛАССАХ
    • Классы в Python – тоже объекты
    >>> type(Number())

    >>> type(Number)

    • Их можно динамически создавать
    def number2_init(self, value):
    self.value = value
    Number2 = type('Number2', (), {'__init__': number2_init})
    type(,
    , # для наследования, может быть пустым
    )

    View Slide

  7. МЕТАКЛАССЫ
    • Метакласс – это «штука», которая создает классы
    MyClass = MetaClass()
    MyObject = MyClass()
    • Type – тоже метакласс
    >>> print(Number.__class__)

    >>> print(int.__class__)

    >>> print(type.__class__)

    View Slide

  8. АЛГОРИТМ ПОИСКА МЕТАКЛАССА
    • Есть ли у класса Foo атрибут __metaclass__?
    • Если да, создаёт в памяти объект-класс с именем Foo, используя то, что
    указано в __metaclass__.
    • Если Питон не находит __metaclass__, он ищет __metaclass__ в родительском
    классе Bar и попробует сделать то же самое.
    • Если же __metaclass__ не находится ни в одном из родителей, Питон будет
    искать __metaclass__ на уровне модуля.
    • И если он не может найти вообще ни одного __metaclass__, он использует type
    для создания объекта-класса.

    View Slide

  9. ПОЛЬЗОВАТЕЛЬСКИЕ МЕТАКЛАССЫ
    • В Python можно создавать свои метаклассы
    • Основная цель – автоматически менять классы в момент
    создания
    • Кстати, метаклассом может быть и функция (не обязательно
    класс)

    View Slide

  10. ПОЛЬЗОВАТЕЛЬСКИЙ МЕТАКЛАСС
    def randomize_name(string):
    data = list(string)
    random.shuffle(data)
    return ''.join(data)
    def shuffler_metaclass(future_class_name, future_class_parents, future_class_attr):
    attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__’))
    shuffled_attrs = dict((randomize_name(name), value) for name, value in attrs)
    return type(future_class_name, future_class_parents, shuffled_attrs)
    class Foo(metaclass=shuffler_metaclass):
    bar = 1

    View Slide

  11. ИЛИ ТОЖЕ САМОЕ КЛАССОМ
    class ShufflerMetaclass(type):
    def __new__(self, name, bases, dct):
    attrs = ((name, value) for name, value in dct.items() if not name.startswith('__’))
    shuffled_attrs = dict((randomize_name(name), value) for name, value in attrs)
    return super(ShufflerMetaclass, self).__new__(self, name, bases, shuffled_attrs)

    View Slide

  12. ЗАЧЕМ НУЖНЫ МЕТАКЛАССЫ?
    Метаклассы это глубокая магия, о которой 99% пользователей
    даже не нужно задумываться. Если вы думаете, нужно ли вам их
    использовать — вам не нужно (люди, которым они реально
    нужны, точно знают, зачем они им, и не нуждаются в
    объяснениях, почему).
    Тим Питерс

    View Slide

  13. СОЗДАНИЕ ЭКЗЕМПЛЯРА КЛАССА
    class Number:
    def __init__(self, value):
    self.value = value
    n = Number(5)
    Простой ответ – вызывается init. Правильный ли он? – не совсем =)
    Создание класса – это просто вызов метакласса.

    View Slide

  14. ЧТО ПРОИСХОДИТ ПРИ СОЗДАНИИ
    ОБЪЕКТА
    • Берем метакласс и вызываем __new_
    • __new__ возвращает экземпляр класса
    • Интерпретатор вызывает __init__ у экземпляра класса

    View Slide

  15. ИСПОЛЬЗОВАНИЕ АТРИБУТОВ
    class Number:
    def __init__(self, value):
    self.value = value
    def __add__(self, target):
    return Number(self.value + target.value)
    a = Number(5)
    b = Number(6)
    (a + b).value
    # 11

    View Slide

  16. ПОИСК АТРИБУТОВ
    • Атрибут __dict__
    >>> Number.__dict__
    {'__module__': '__main__’,
    '__init__': ,
    '__add__': ,
    '__dict__': ,
    '__weakref__': ,
    '__doc__': None})
    >>> Number(4).__dict__
    {'value': 4}

    View Slide

  17. ПОИСК АТРИБУТОВ
    • Для обычных атрибутов
    • Вызывается number.__getattribute__(‘value’)
    • Сначала ищем в __dict__ экземпляра
    • Потом ищем в __dict__ класса и его родителях
    • Для атрибутов, начинающихся с двойного нижнего подчеркивания, поиск
    происходит напрямую в классе (__add__)

    View Slide

  18. GETATTR
    • __getattr__ вызывается только в случае, когда атрибут не найден
    обычным способом
    • Сначала вызывается __getattribute__, если он райзит AttributeError
    вызывается __getattr__

    View Slide

  19. ВРОДЕ ПОНЯТНО?

    View Slide

  20. ВРОДЕ ПОНЯТНО?
    class Number:
    def __init__(self, value):
    self.value = value
    def __add__(self, target):
    return Number(self.value + target.value)
    def square(self):
    return Number(self.value**2)
    >>> n = Number(4)
    >>> Number.square

    >>> n.square
    object at 0x10c68d828>>

    View Slide

  21. ДЕСКРИПТОРЫ
    • Дескриптор — это объект-атрибут объекта со связанным поведением
    (англ.binding behavior)
    • Поведение при доступе переопределяется методами протокола
    дескриптора.
    • __get__
    • __set__
    • __delete__
    • Наличие хотя бы одно из этих методов делает объект дескриптором.

    View Slide

  22. ДЕСКРИПТОРЫ
    def __getattribute__(self, key):
    v = object.__getattribute__(self, key)
    if hasattr(v, '__get__’):
    return v.__get__(None, self)
    return v

    View Slide

  23. FUNCTION
    class Function(object):
    def __get__(self, obj, objtype=None):
    if obj is None:
    return self
    return types.MethodType(self, obj)

    View Slide

  24. УДАЛЕНИЕ ОБЪЕКТА
    • Метод __del__ вызывается, когда Питон удаляет объект…
    ВОЗМОЖНО!
    • Python не гарантирует вызов __del__
    • __del__ скорее всего не вызовется
    • Если объект – часть ссылочного цикла
    • Живет до конца (умирает вместе с интерпретатором)
    • Если __del__ приводит к появлению еще одной ссылки на объект

    View Slide

  25. УДАЛЕНИЕ ОБЪЕКТА - ПРАКТИКИ
    • Не использовать __del__
    • Менеджер контекста или try/finally

    View Slide

  26. ИТОГ
    • Теперь живите с этим
    • Узнали, что Python не так прост
    • Стали лучше понимать как работает магия в фреймворках
    • Может удивить своими знаниями на собеседовании (например в
    ДомКлик)

    View Slide

  27. ПОЛЕЗНЫЕ МАТЕРИАЛЫ
    • https://speakerdeck.com/pycon2016/mike-graham-the-life-cycle-of-a-
    python-class
    • https://habr.com/post/145835/
    • https://docs.python.org/3/howto/descriptor.html#functions-and-
    methods

    View Slide