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

December 27, 2018
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. ОБО МНЕ • Директор разработки • Работа с данными &

    DS • Докладчик PyCon 2017, PyCon 2018, MoscowPython, … • Не люблю гироскутеры, смузи и вот это все
  2. О КОМПАНИИ • Ипотека онлайн • Доп продукты • Маркетплейс

    недвижимости • Python, Asyncio, Postgresql • ML NLP&CV
  3. СОЗДАНИЕ ЭКЗЕМПЛЯРА КЛАССА class Number: def __init__(self, value): self.value =

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

    value n = Number(5) Простой ответ – вызывается init. Правильный ли он? не совсем =)
  5. ПОГОВОРИМ НЕМНОЖКО О МЕТАКЛАССАХ • Классы в Python – тоже

    объекты >>> type(Number()) <class '__main__.Number’> >>> type(Number) <class 'type'> • Их можно динамически создавать def number2_init(self, value): self.value = value Number2 = type('Number2', (), {'__init__': number2_init}) type(<имя класса>, <кортеж родительских классов>, # для наследования, может быть пустым <словарь, содержащий атрибуты и их значения>)
  6. МЕТАКЛАССЫ • Метакласс – это «штука», которая создает классы MyClass

    = MetaClass() MyObject = MyClass() • Type – тоже метакласс >>> print(Number.__class__) <class 'type’> >>> print(int.__class__) <class 'type’> >>> print(type.__class__) <class 'type'>
  7. АЛГОРИТМ ПОИСКА МЕТАКЛАССА • Есть ли у класса Foo атрибут

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

    Основная цель – автоматически менять классы в момент создания • Кстати, метаклассом может быть и функция (не обязательно класс)
  9. ПОЛЬЗОВАТЕЛЬСКИЙ МЕТАКЛАСС 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
  10. ИЛИ ТОЖЕ САМОЕ КЛАССОМ 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)
  11. ЗАЧЕМ НУЖНЫ МЕТАКЛАССЫ? Метаклассы это глубокая магия, о которой 99%

    пользователей даже не нужно задумываться. Если вы думаете, нужно ли вам их использовать — вам не нужно (люди, которым они реально нужны, точно знают, зачем они им, и не нуждаются в объяснениях, почему). Тим Питерс
  12. СОЗДАНИЕ ЭКЗЕМПЛЯРА КЛАССА class Number: def __init__(self, value): self.value =

    value n = Number(5) Простой ответ – вызывается init. Правильный ли он? – не совсем =) Создание класса – это просто вызов метакласса.
  13. ЧТО ПРОИСХОДИТ ПРИ СОЗДАНИИ ОБЪЕКТА • Берем метакласс и вызываем

    __new_ • __new__ возвращает экземпляр класса • Интерпретатор вызывает __init__ у экземпляра класса
  14. ИСПОЛЬЗОВАНИЕ АТРИБУТОВ 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
  15. ПОИСК АТРИБУТОВ • Атрибут __dict__ >>> Number.__dict__ {'__module__': '__main__’, '__init__':

    <function Number.__init__ at 0x10c673ea0>, '__add__': <function Number.__add__ at 0x10c673f28>, '__dict__': <attribute '__dict__' of 'Number' objects>, '__weakref__': <attribute '__weakref__' of 'Number' objects>, '__doc__': None}) >>> Number(4).__dict__ {'value': 4}
  16. ПОИСК АТРИБУТОВ • Для обычных атрибутов • Вызывается number.__getattribute__(‘value’) •

    Сначала ищем в __dict__ экземпляра • Потом ищем в __dict__ класса и его родителях • Для атрибутов, начинающихся с двойного нижнего подчеркивания, поиск происходит напрямую в классе (__add__)
  17. GETATTR • __getattr__ вызывается только в случае, когда атрибут не

    найден обычным способом • Сначала вызывается __getattribute__, если он райзит AttributeError вызывается __getattr__
  18. ВРОДЕ ПОНЯТНО? 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 <function Number.square at 0x10c697158> >>> n.square <bound method Number.square of <__main__.Number object at 0x10c68d828>>
  19. ДЕСКРИПТОРЫ • Дескриптор — это объект-атрибут объекта со связанным поведением

    (англ.binding behavior) • Поведение при доступе переопределяется методами протокола дескриптора. • __get__ • __set__ • __delete__ • Наличие хотя бы одно из этих методов делает объект дескриптором.
  20. FUNCTION class Function(object): def __get__(self, obj, objtype=None): if obj is

    None: return self return types.MethodType(self, obj)
  21. УДАЛЕНИЕ ОБЪЕКТА • Метод __del__ вызывается, когда Питон удаляет объект…

    ВОЗМОЖНО! • Python не гарантирует вызов __del__ • __del__ скорее всего не вызовется • Если объект – часть ссылочного цикла • Живет до конца (умирает вместе с интерпретатором) • Если __del__ приводит к появлению еще одной ссылки на объект
  22. ИТОГ • Теперь живите с этим • Узнали, что Python

    не так прост • Стали лучше понимать как работает магия в фреймворках • Может удивить своими знаниями на собеседовании (например в ДомКлик)