Classes and objects Flashcards

(14 cards)

1
Q

Как получить список атрибутов объекта

A

Функция dir возвращает список строк – полей объекта. Поле __dict__ содержит словарь вида {поле -> значение}.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Что такое магические методы, для чего нужны

A

Магическими метода называют методы, имена которых начинаются и заканчиваются двойным подчеркиванием. Магические они потому, что почти никогда не вызываются явно. Их вызывают встроенные функции или синтаксические конструкции. Например, функция len() вызывает метод __len__() переданного объекта. Метод __add__(self, other) вызывается автоматически при сложении оператором +.

Перечислим некоторые магические методы:

__init__: инициализатор класса
__add__: сложение с другим объектом
__eq__: проверка на равенство с другим объектом
__iter__: возвращает итератор

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Как в классе сослаться на родительский класс

A

Функция super принимает класс и экземпляр:

class NextClass(FirstClass):
def __init__(self, x):
super(NextClass, self).__init__()
self.x = x

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Возможно ли множественное наследование

A

Да, можно указать более одного родителя в классе потомка.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Что такое MRO

A

MRO – method resolution order, порядок разрешения методов. Алгоритм, по которому следует искать метод в случае, если у класса два и более родителей.

В классических классах поиск при наследовании по ссылкам на имена осуществляется в следующем порядке:

Сначала экземпляр
Затем его класс
Далее все суперклассы его класса с обходом сначала с глубину, а затем слева направо
Используется первое обнаруженное вхождение. Такой порядок называется DFLR (Обход вглубину и слева направо).

При наследовании классов нового стиля применяется правило MRO (порядок разрешения методов), т.е линеаризованный обход дерева классов, причем вложенный элемент наследования становится доступным в атрибуте __mro__ данного класса. Такой алгорим называется C3-линеаризация. Наследование по правилу MRO осуществляется приблизительно в следующем порядке.

Перечисление всех классов, наследуемых экземпляром, по правилу поиска DFLR для классических классов, причем класс включается в результат поиска столько раз, сколько он встречается при обходе.
Просмотр в полученном списке дубликатов классов, из которых удаляются все, кроме последнего (крайнего справа) дубликата в списке.
Упорядочение по правилу MRO применяется при наследовании и вызове встроенной функции super(), которая всегда вызывает следующий по правилу MRO класс (относительно точки вызова).

Пример наследования в неромбовидных иерархаических деревьях:

class D: attr = 3 # D:3 E:2
class B(D) pass # | |
class E: attr = 2 # B C:1
class C(E): attr = 1 # / /
class A(B, C): pass # A
X = A() # |
print(X.attr) # X

DFLR = [X, A, B, D, C, E]
# MRO = [X, A, B, D, C, E, object]
# И в версии 3.х и в версии 2.х (всегда) выводит строку “3”
Пример наследования в ромбовидных иерархаических деревьях:

class D: attr = 3 # D:3 D:3
class B(D) pass # | |
class C(D): attr = 1 # B C:1
class A(B, C): pass # / /
X = A() # A
print(X.attr) # |
# X

DFLR = [X, A, B, D, C, D]
# MRO = [X, A, B, C, D, object] (сохраняет только последний дубликат D)
# Выводит строку “1” в версии 3.х, строку “3” в версии 2.х (“1” если D(object))

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Что такое Diamond problem

A

При ромбовидном наследовании определить метод какого класса должен быть вызван

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Что такое миксины

A

Миксин (mix-in, анг. “примесь”), паттерн проектирования в ООП, когда в цепочку наследования добавляется небольшой класс-помощник. Например, есть класс

class NowMixin(object):
def now():
return datetime.datetime.utcnow()
Тогда любой класс, наследованный с этим миксином, будет иметь метод now().

В названия миксинов принято добавлять слово Mixin, так как не существует никакого механизма для понимания полноценный это класс или миксин. Миксин технически является самым обычным классом

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Что такое контекстный менеджер. Как написать свой

A

В питоне есть оператор with. Размещенный внутри код выполняется с особенностью: до и после гарантированно срабатывают события входа в блок withи выхода из него. Объект, который определяет эту логику, называется контекстным менеджером.

События входа и выхода из блока определены методами __enter__ и __exit__. Первый срабатывает в тот момент, когда ход исполнения программы переходит внутрь with. Метод может вернуть значение. Оно будет доступно низлежащему внутри блока with коду.

__exit__ срабатывает в момент выхода из блока, в т.ч. и по причине исключения. В этом случае в метод будет передана тройка значений (exc_class, exc_instance, traceback).

Самый распространённый контекстный менеджер – класс, порожденный функцией open. Он гарантирует, что файл будет закрыт даже в том случае, если внутри блока возникнет ошибка.

Нужно стараться выходить из контекстного менеджера как можно быстрее, чтобы освобождать контекст и ресурсы.

with open(‘file.txt’) as f:
data = f.read()
process_data(data)
Пример реализации своего контекстного менеджера на основе класса:

class Printable:
def __enter__(self):
print(‘enter’)

def \_\_exit\_\_(self, type, value, traceback):
    print('exit')

Пример реализации своего контекстного менеджера с использованием встроенной библиотеки contextlib:

from contextlib import contextmanager

@contextmanager
def printable():
print(‘enter’)
try:
yield
finally:
print(‘exit’)

Контекстные менеджеры также можно использовать для временной замены параметров, переменных окружения, транзакций БД.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Прокомментировать выражение

A

object() == object()

Всегда ложь, поскольку по умолчанию объекты сравниваются по полю id (адрес в памяти), если только не переопределен метод __eq__.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Что такое __slots__. Плюсы, минусы

A

Классы хранят поля и их значения в секретном словаре __dict__. Поскольку словарь – изменяемая структура, вы можете на лету добавлять и удалять из класса поля. Параметр __slots__ в классе жестко фиксирует набор полей класса. Слоты используются когда у класса может быть очень много полей, например, в некоторых ORM, либо когда критична производительность, потому что доступ к слоту срабатывает быстрее, чем поиск в словаре, или когда в процессе выполнения программы создаются миллионы экземпляров класса, применение __slots__ позволит сэкономить память.

Слоты активно используются в библиотеках requests и falcon.

Недостатотк: нельзя присвоить классу поле, которого нет в слотах. Не работают методы __getattr__ и __setattr__. Решение: включить в __slots__ элемент __dict__

В чем смысл параметров _value, __value
Поле класса с одним лидирующим подчеркиванием говорит о том, что параметр используется только внутри класса. При этом он доступен для обращения извне. Это ограничение доступа только на уровне соглашения.

class Foo(object):
def __init__(self):
self._bar = 42

Foo()._bar
»> 42

Современные IDE вроде PyCharm подсвечивают обращение к полю с подчеркиванием, но ошибки в процессе исполнения не будет.

Поля с двойным подчеркиванием доступны внутри класса, но недоступны извне. Это достигается хитрым приемом: интерпретатор назначает таким полям имена вида _<ClassName>\_\_<fieldName>. Описанный механизм называется name mangling или name decoration</fieldName></ClassName>

class Foo(object):
def __init__(self):
self.__bar = 42

Foo().__bar
»> AttributeError: ‘Foo’ object has no attribute ‘__bar’
Foo()._Foo__bar
»> 42

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Что такое __new__. И чем он отличается от __init__. В какой последовательности они выполняются

A

Основное различие между этими двумя методами состоит в том, что __new__ обрабатывает создание объекта, а __init__ обрабатывает его инициализацию.

__new__ вызывается автоматически при вызове имени класса (при создании экземпляра), тогда как __init__ вызывается каждый раз, когда экземпляр класса возвращается __new__, передавая возвращаемый экземпляр в __init__ в качестве параметра self, поэтому даже если вы сохранили экземпляр где-нибудь глобально/статически и возвращали его каждый раз из __new__, для него все-равно будет каждый раз вызываться __init__.

Из вышесказанного вытекает что сначала вызывается __new__, а потом __init__

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Что такое и чем отличается old-style от new-style classes

A

Классы нового стиля (3.х доступны только они, в 2.х при наследовании от object) отличаются от классических (по умолчанию в 2.х) следующими особенностями:

Причиной создания new style classes послужила идея убрать отличие встроенных типов от определённых пользователем типов. Unifying types and classes in Python 2.2
Ромбовидные шаблоны множественного наследования имеют несколько иной порядок поиска. Поиск в них осуществляется скорее в ширину, чем в глубину, перед тем как начать обход снизу вверх (см. вопрос про MRO)
Классы теперь обозначают типы, а типы являются классами. Так, в результате вызова встроенной функции type(I) возвращается класс, из которого получается экземпляр, а не тип экземпляра, что, как правило, равнозначно выражению I.__class__. От класса type могут быть произведены подклассы для создания специальных классов. Все классы наследуют от встроенного класса object, предоставляющего по умолчанию небольшой набор методов

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Что такое утиная типизация

A

Неявная типизация, латентная типизация или утиная типизация (англ. Duck typing) – вид динамической типизации, применяемой в некоторых языках программирования (Perl, Smalltalk, Python, Objective-C, Ruby, JavaScript, Groovy, ColdFusion, Boo, Lua, Go, C#), когда границы использования объекта определяются его текущим набором методов и свойств, в противоположность наследованию от определённого класса. То есть считается, что объект реализует интерфейс, если он содержит все методы этого интерфейса, независимо от связей в иерархии наследования и принадлежности к какому-либо конкретному классу.

Утиная типизация решает такие проблемы иерархической типизации, как:

невозможность явно указать (путём наследования) на совместимость интерфейса со всеми настоящими и будущими интерфейсами, с которыми он идейно совместим;
экспоненциальное увеличение числа связей в иерархии типов при хотя бы частичной попытке это сделать

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q
A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly