Python | Вопросы собесов
13.4K subscribers
17 photos
1 file
343 links
Разбираем вопросы с собеседований на Python разработчика. Django, Flask, FastApi

Реклама: @easyoffer_adv
Решай тесты - t.me/+20tRfhrwPpM4NDQy

Нарешивай задачи - t.me/+nsl4meWmhfQwNDVi
Ищи работу - t.me/+cXGKkrOY2-w3ZTky
Download Telegram
Какой метод декоратора property позволяет установить значение атрибута, при этом применяя дополнительные проверки или вычисления?
Anonymous Quiz
16%
getter
67%
setter
1%
deleter
16%
updater
Как в python реализуются метод объекта ?
Спросят с вероятностью 3%

Методы объекта реализуются как функции, определённые внутри класса. Они могут работать с данными объекта и предоставляют интерфейс для взаимодействия с экземплярами класса. Важным аспектом методов объекта является то, что они принимают первым параметром self, который является ссылкой на экземпляр класса.

Пример реализации методов объекта
class MyClass:
def __init__(self, value):
self.value = value # Инициализация атрибута

def display_value(self):
print(f"The value is: {self.value}") # Метод для вывода значения атрибута

def increment_value(self, amount):
self.value += amount # Метод для увеличения значения атрибута на заданное количество

# Создание экземпляра класса
obj = MyClass(10)

# Вызов методов объекта
obj.display_value() # Выведет: The value is: 10
obj.increment_value(5)
obj.display_value() # Выведет: The value is: 15


Объяснение кода

1️⃣Конструктор __init__:
Метод реализуютявляется специальным методом, который вызывается при создании нового экземпляра класса.
Он используется для инициализации атрибутов экземпляра.

2️⃣Метод display_value:
Этот метод выводит текущее значение атрибута value.
Он принимает только один параметр self, который автоматически передаётся при вызове метода у объекта.

3️⃣Метод increment_value:
Этот метод увеличивает значение атрибута value на заданное количество.
Он принимает два параметра: self и amount, где self — это ссылка на экземпляр, а amount — значение, на которое нужно увеличить value.

Использование self

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

Методы экземпляра, класса и статические методы

В дополнение к обычным методам объекта, также можно определить методы класса и статические методы.

1️⃣Методы класса:
Методы класса используют декоратор @classmethod и принимают первым параметром cls, который является ссылкой на сам класс.
Они полезны для работы с атрибутами класса или для создания экземпляров альтернативными способами.
class MyClass:
class_value = 0

def __init__(self, value):
self.value = value

@classmethod
def set_class_value(cls, new_value):
cls.class_value = new_value

# Вызов метода класса
MyClass.set_class_value(10)
print(MyClass.class_value) # Выведет: 10


2️⃣Статические методы:
Статические методы используют декоратор @staticmethod и не принимают ни self, ни cls.
Они полезны для функций, которые не зависят от состояния экземпляра или класса.
class MyClass:
@staticmethod
def static_method():
print("This is a static method")

# Вызов статического метода
MyClass.static_method() # Выведет: This is a static method


Методы объекта — это функции, определённые внутри класса, которые работают с данными экземпляра через параметр self. Методы класса и статические методы также могут быть определены с использованием декораторов @classmethod и @staticmethod соответственно.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какой магический метод используется для перегрузки оператора умножения для экземпляра класса?
Anonymous Quiz
71%
__mul__
9%
__add__
9%
__div__
11%
__mod__
Какие методы в метаклассах используются ?
Спросят с вероятностью 3%

Метаклассы предоставляют возможность управления созданием и поведением классов. Основными методами, которые используются в метаклассах, являются:

1️⃣`__new__`: Отвечает за создание нового класса. Он вызывается до __init__ и используется для создания нового объекта класса. В метаклассе new позволяет изменять процесс создания класса.

2️⃣`__init__`: Инициализирует класс, после того как он был создан. В метаклассе init используется для модификации созданного класса, например, добавления атрибутов или методов.

3️⃣`__call__`: Позволяет метаклассу контролировать процесс создания экземпляров класса. Он вызывается, когда создаётся новый объект класса.

Рассмотрим пример использования этих методов:
class MyMeta(type):
def __new__(cls, name, bases, dct):
print(f'Creating class {name}')
# Добавление нового атрибута
dct['added_attribute'] = 'I was added by MyMeta'
return super().__new__(cls, name, bases, dct)

def __init__(cls, name, bases, dct):
print(f'Initializing class {name}')
super().__init__(name, bases, dct)

def __call__(cls, *args, **kwargs):
print(f'Creating instance of class {cls.__name__}')
return super().__call__(*args, **kwargs)

class MyClass(metaclass=MyMeta):
def __init__(self):
print('Instance initialized')

# Создание экземпляра класса
instance = MyClass()
print(instance.added_attribute)


В этом примере:
Метод
ating ins
добавляет новый атрибут added_attribute к классу.
Метод init выполняет инициализацию класса и может быть использован для дальнейших модификаций.
Метод call контролирует создание экземпляров класса и выполняет необходимые действия при создании нового объекта.

Методы new, init и call в метаклассах используются для управления процессами создания и инициализации классов, а также создания их экземпляров. Они позволяют модифицировать классы на различных этапах их жизненного цикла.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Что такое diamondproblem ?
Спросят с вероятностью 3%

Проблема ромбовидного наследования (Diamond Problem) возникает в ООП при использовании множественного наследования. Суть проблемы заключается в неоднозначности, возникающей из-за наследования от нескольких классов, имеющих общего предка.

Рассмотрим пример:
class A:
def method(self):
print("Method in A")

class B(A):
def method(self):
print("Method in B")

class C(A):
def method(self):
print("Method in C")

class D(B, C):
pass

d = D()
d.method()


В этом примере:
Класс A является базовым классом.
Классы B и C наследуют от класса A и переопределяют метод method.
Класс D наследует от классов B и C.

Когда мы вызываем метод method через экземпляр класса D (d.method()), возникает вопрос: какой именно метод должен быть вызван - из класса B или из класса C? Это и есть проблема ромбовидного наследования.

Решение проблемы ромбовидного наследования

Использует метод разрешения порядка (MRO - Method Resolution Order) для решения этой проблемы. MRO определяет порядок, в котором методы должны вызываться в случае множественного наследования. Для просмотра MRO можно использовать атрибут __mro__ или функцию mro().
print(D.__mro__)


Результат будет следующим:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)


Согласно этому порядку, метод method будет взят из класса B, так как он идёт первым в MRO. Поэтому при вызове d.method(), выведется:
Method in B

Если классы B и C используют super(), можно правильно вызвать методы всех классов-предков:
class A:
def method(self):
print("Method in A")

class B(A):
def method(self):
print("Method in B")
super().method()

class C(A):
def method(self):
print("Method in C")
super().method()

class D(B, C):
def method(self):
print("Method in D")
super().method()

d = D()
d.method()


Результат выполнения будет:
Method in D
Method in B
Method in C
Method in A


В этом случае методы всех классов вызываются в порядке, определённом MRO.

Проблема ромбовидного наследования возникает при множественном наследовании и приводит к неоднозначности, какой метод вызывать. Решает эту проблему с помощью MRO (Method Resolution Order), определяющего порядок вызова методов.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Что такое объект класса ?
Спросят с вероятностью 3%

Объект класса, или просто объект
, — это экземпляр класса, созданный на основе его шаблона. Класс в ООП служит как чертеж для создания объектов. Он определяет атрибуты (данные) и методы (функции), которые объект будет иметь.

Создание класса и объектов

Рассмотрим пример:

class Dog:
def __init__(self, name, age):
self.name = name
self.age = age

def bark(self):
print(f"{self.name} is barking")

# Создание объектов класса Dog
dog1 = Dog("Buddy", 3)
dog2 = Dog("Molly", 5)

# Вызов метода объекта
dog1.bark() # Выведет: Buddy is barking
dog2.bark() # Выведет: Molly is barking


В этом примере:

1️⃣Класс Dog: определяет два атрибута (name и age) и один метод (bark).
2️⃣Конструктор init: метод, который вызывается при создании нового объекта. Он инициализирует атрибуты объекта.
3️⃣Объекты dog1 и dog2: создаются на основе класса Dog и являются его экземплярами.

Важные аспекты

1️⃣Атрибуты: данные, хранящиеся в объекте. Например, dog1.name и dog1.age — это атрибуты объекта dog1.
2️⃣Методы: функции, определенные в классе, которые могут быть вызваны для объекта. Например, dog1.bark() вызывает метод bark объекта dog1.
3️⃣Инкапсуляция: механизм объединения данных (атрибутов) и методов для работы с этими данными в одном объекте.
4️⃣Полиморфизм: возможность объектов разного класса предоставлять одинаковый интерфейс для работы.
5️⃣Наследование: возможность создавать новый класс на основе существующего, унаследуя его атрибуты и методы.

Пример с наследованием
class Animal:
def __init__(self, species):
self.species = species

def make_sound(self):
pass

class Dog(Animal):
def __init__(self, name, age):
super().__init__("Dog")
self.name = name
self.age = age

def bark(self):
print(f"{self.name} is barking")

def make_sound(self):
self.bark()

dog1 = Dog("Buddy", 3)
dog1.make_sound() # Выведет: Buddy is barking


В этом примере:
Класс Animal является базовым классом.
Класс Dog наследует от Animal и добавляет свои методы и атрибуты.
Метод make_sound переопределяется в классе Dog для реализации специфического поведения.

Объект класса — это конкретный экземпляр класса с собственными атрибутами и методами. Класс определяет структуру объектов, а объект является конкретной реализацией этой структуры.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Что такое cls ?
Спросят с вероятностью 3%

cls — это имя, принятое по соглашению для первого параметра методов класса. Он используется аналогично тому, как self используется в методах экземпляра. В то время как self ссылается на конкретный объект (экземпляр) класса, cls ссылается на сам класс.

Методы класса

Это методы, которые получают сам класс в качестве первого аргумента. Для их создания используется декоратор @classmethod.

Рассмотрим пример:

class MyClass:
class_variable = 0

def __init__(self, value):
self.instance_variable = value

@classmethod
def class_method(cls, increment):
cls.class_variable += increment
print(f"Class variable is now {cls.class_variable}")

# Создание экземпляров
obj1 = MyClass(1)
obj2 = MyClass(2)

# Вызов метода класса
MyClass.class_method(5) # Выведет: Class variable is now 5
obj1.class_method(3) # Выведет: Class variable is now 8
obj2.class_method(2) # Выведет: Class variable is now 10


В этом примере:

Класс MyClass: имеет переменную класса class_variable и метод класса class_method.
Метод класса class_method: использует cls для доступа и изменения переменной класса.

Почему он используется

1️⃣Доступ к атрибутам класса: Методы класса могут изменять состояние класса, а не конкретного экземпляра.
2️⃣Создание альтернативных конструкторов: Часто используется для создания дополнительных способов инициализации объектов.

Пример:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

@classmethod
def from_birth_year(cls, name, birth_year):
age = 2024 - birth_year
return cls(name, age)

# Создание объектов с использованием альтернативного конструктора
person1 = Person("Alice", 30)
person2 = Person.from_birth_year("Bob", 1990)

print(person1.name, person1.age) # Выведет: Alice 30
print(person2.name, person2.age) # Выведет: Bob 34


В этом примере:
Метод класса from_birth_year использует cls для создания нового объекта Person, рассчитывая возраст на основе года рождения.

cls используется в методах класса для ссылки на сам класс. Он позволяет методам класса изменять состояние класса и создавать альтернативные конструкторы.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как в python реализуются public метод ?
Спросят с вероятностью 3%

Методы по умолчанию являются публичными (public). Это означает, что они доступны для вызова из любого места, где доступен объект класса. Публичные методы предназначены для взаимодействия с объектом извне и предоставляют интерфейс для выполнения действий или получения данных.

Пример:

class MyClass:
def __init__(self, value):
self.value = value

def public_method(self):
print(f"The value is {self.value}")

# Создание экземпляра класса
obj = MyClass(10)

# Вызов публичного метода
obj.public_method() # Выведет: The value is 10


В этом примере:

Метод public_method является публичным, поскольку он определён без каких-либо специальных модификаторов и доступен извне.

Как их отличить

Принято использовать соглашения об именах для различения публичных и непубличных (приватных и защищённых) методов:
1️⃣Публичные методы: не имеют подчёркиваний в начале имени.
2️⃣Защищённые методы: имеют одно подчёркивание в начале имени (_method).
3️⃣Приватные методы: имеют два подчёркивания в начале имени (__method).

Однако следует помнить, что эти соглашения носят рекомендательный характер и не обеспечивают жёсткого ограничения доступа, как в некоторых других языках программирования.

Пример для всех типов методов
class MyClass:
def __init__(self, value):
self.value = value

def public_method(self):
print(f"Public method: The value is {self.value}")

def _protected_method(self):
print(f"Protected method: The value is {self.value}")

def __private_method(self):
print(f"Private method: The value is {self.value}")

def access_private_method(self):
self.__private_method()

# Создание экземпляра класса
obj = MyClass(10)

# Вызов публичного метода
obj.public_method() # Выведет: Public method: The value is 10

# Вызов защищённого метода (можно, но не рекомендуется)
obj._protected_method() # Выведет: Protected method: The value is 10

# Вызов приватного метода напрямую приведёт к ошибке
# obj.__private_method() # АтрибутError

# Вызов приватного метода через публичный метод
obj.access_private_method() # Выведет: Private method: The value is 10


Почему использовать публичные методы

1️⃣Интерфейс для взаимодействия: Публичные методы предоставляют способ взаимодействия с объектом, позволяя выполнять действия или получать данные.
2️⃣Инкапсуляция: Они помогают скрывать внутреннюю реализацию класса, предоставляя только необходимые для пользователя методы.

Публичные методы доступны для вызова из любого места. Они предоставляют интерфейс для взаимодействия с объектом и обычно не имеют подчёркиваний в начале имени.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Что будет, если в родительских классах есть функции с одинаковым названием ?
Спросят с вероятностью 3%

Если у родительских классов есть функции с одинаковым названием, и они наследуются дочерним классом, возникает проблема множественного наследования. В этом случае Python использует порядок разрешения методов (Method Resolution Order, MRO), чтобы определить, какую версию функции использовать.

Порядок разрешения методов (MRO)

Использует алгоритм C3-линеаризации для определения MRO. Порядок MRO определяет, в каком порядке Python будет искать методы в иерархии классов. Вы можете увидеть MRO с помощью атрибута __mro__ или метода mro().

Рассмотрим пример, где два родительских класса имеют методы с одинаковым названием:
class A:
def method(self):
print("Method from class A")

class B:
def method(self):
print("Method from class B")

class C(A, B):
pass

# Создание экземпляра класса C и вызов метода
c = C()
c.method() # Выведет: Method from class A


В данном случае класс C наследует от A и B. При вызове метода method у экземпляра C Python сначала проверяет класс C, затем A (первый родитель) и только потом B (второй родитель). Таким образом, вызывается метод из класса A.

Вы можете проверить порядок MRO следующим образом:
print(C.__mro__)
# Выведет: (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)


Или с помощью метода mro():
print(C.mro())
# Выведет: [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]


Влияние порядка наследования

Если поменять порядок наследования в определении класса C, результат изменится:
class C(B, A):
pass

c = C()
c.method() # Выведет: Method from class B


Теперь метод из класса B будет вызван первым, так как B указан перед A в списке родительских классов.

Можно также переопределить метод в дочернем классе, чтобы явно указать, какой метод использовать:
class C(A, B):
def method(self):
print("Method from class C")

c = C()
c.method() # Выведет: Method from class C


Если нужно вызвать метод из конкретного родительского класса, можно использовать super():
class C(A, B):
def method(self):
super(A, self).method() # Вызывает метод из класса B, так как он идет следующим после A в MRO

c = C()
c.method() # Выведет: Method from class B


Если у родительских классов есть функции с одинаковым названием, использует порядок разрешения методов (MRO) для определения, какой метод вызывать. Вы можете проверить порядок MRO с помощью атрибута mro или метода mro(). Порядок наследования в определении класса влияет на MRO и на то, какой метод будет вызван.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как в python реализуются private метод ?
Спросят с вероятностью 3%

Приватные методы реализуются с помощью двойного подчёркивания (двойного подчеркивания) перед именем метода. Такое именование запускает механизм "name mangling" (искажение имени), который делает метод менее доступным для прямого вызова из-за пределов класса, добавляя к имени метода имя класса.

Пример:

class MyClass:
def __init__(self, value):
self.value = value

def __private_method(self):
print(f"Private method: The value is {self.value}")

def public_method(self):
self.__private_method()

# Создание экземпляра класса
obj = MyClass(10)

# Вызов публичного метода
obj.public_method() # Выведет: Private method: The value is 10

# Прямой вызов приватного метода приведёт к ошибке
# obj.__private_method() # AttributeError: 'MyClass' object has no attribute '__private_method'


В этом примере:
Метод __private_method является приватным и не может быть вызван напрямую извне класса.

Доступ к приватным методам

Хотя позволяет скрывать методы с помощью двойного подчёркивания, это не является абсолютной защитой. Имя метода изменяется по правилу _<имя_класса>__<имя_метода>. Это позволяет, при необходимости, получить доступ к приватным методам:
# Доступ к приватному методу через name mangling
obj._MyClass__private_method() # Выведет: Private method: The value is 10


Почему они используются

1️⃣Инкапсуляция: Помогают скрывать внутреннюю реализацию класса и защищают данные и методы от несанкционированного доступа и изменения.
2️⃣Упрощение интерфейса: Скрывая детали реализации, приватные методы позволяют сосредоточиться на использовании класса через его публичный интерфейс.
3️⃣Предотвращение конфликтов имён: Приватные методы уменьшают вероятность конфликтов имён при наследовании классов.

Правила именования

1️⃣Публичные методы: нет подчёркиваний в начале имени.
2️⃣Защищённые методы: одно подчёркивание в начале имени (_method).
3️⃣Приватные методы: два подчёркивания в начале имени (__method).

Пример для всех типов методов
class MyClass:
def __init__(self, value):
self.value = value

def public_method(self):
print(f"Public method: The value is {self.value}")

def _protected_method(self):
print(f"Protected method: The value is {self.value}")

def __private_method(self):
print(f"Private method: The value is {self.value}")

def access_private_method(self):
self.__private_method()

# Создание экземпляра класса
obj = MyClass(10)

# Вызов публичного метода
obj.public_method() # Выведет: Public method: The value is 10

# Вызов защищённого метода (можно, но не рекомендуется)
obj._protected_method() # Выведет: Protected method: The value is 10

# Вызов приватного метода напрямую приведёт к ошибке
# obj.__private_method() # AttributeError

# Вызов приватного метода через публичный метод
obj.access_private_method() # Выведет: Private method: The value is 10

# Доступ к приватному методу через name mangling
obj._MyClass__private_method() # Выведет: Private method: The value is 10


Приватные методы реализуются с помощью двойного подчёркивания перед именем метода. Это скрывает метод, делая его недоступным напрямую извне класса, и помогает в инкапсуляции и защите данных.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как в python реализуются protected метод ?
Спросят с вероятностью 3%

Защищенные (protected) методы реализуются с помощью одного подчёркивания (_) перед именем метода. Это соглашение обозначает, что метод или атрибут не предназначен для использования за пределами класса и его подклассов. Однако, в отличие от приватных методов, защищенные методы не скрываются полностью и могут быть вызваны извне, если необходимо.

Пример:
class MyClass:
def __init__(self, value):
self._protected_value = value

def _protected_method(self):
print(f"Protected method: The value is {self._protected_value}")

def public_method(self):
self._protected_method()

# Создание экземпляра класса
obj = MyClass(10)

# Вызов публичного метода
obj.public_method() # Выведет: Protected method: The value is 10

# Вызов защищенного метода напрямую (возможно, но не рекомендуется)
obj._protected_method() # Выведет: Protected method: The value is 10


В этом примере:

Метод _protected_method является защищенным и обозначен одним подчёркиванием перед именем.
Атрибут _protected_value также является защищенным и обозначен аналогично.

Почему они используются

1️⃣Соглашение об использовании: Одинарное подчёркивание сигнализирует другим программистам, что метод или атрибут не предназначен для публичного использования.
2️⃣Инкапсуляция: Помогает в организации кода и защите внутренних данных и методов, хотя и не предоставляет строгих ограничений доступа.
3️⃣Наследование: Упрощает создание иерархий классов, где подклассы могут использовать методы и атрибуты, предназначенные только для внутреннего использования.

Правила именования

1️⃣Публичные методы: Нет подчёркиваний в начале имени.
2️⃣Защищённые методы: Одно подчёркивание в начале имени (_method).
3️⃣Приватные методы: Два подчёркивания в начале имени (__method).

Пример для всех типов методов
class MyClass:
def __init__(self, value):
self.value = value
self._protected_value = value * 2
self.__private_value = value * 3

def public_method(self):
print(f"Public method: The value is {self.value}")
self._protected_method()
self.__private_method()

def _protected_method(self):
print(f"Protected method: The value is {self._protected_value}")

def __private_method(self):
print(f"Private method: The value is {self.__private_value}")

# Создание экземпляра класса
obj = MyClass(10)

# Вызов публичного метода
obj.public_method() # Выведет:
# Public method: The value is 10
# Protected method: The value is 20
# Private method: The value is 30

# Вызов защищенного метода напрямую (возможно, но не рекомендуется)
obj._protected_method() # Выведет: Protected method: The value is 20

# Прямой вызов приватного метода приведёт к ошибке
# obj.__private_method() # AttributeError: 'MyClass' object has no attribute '__private_method'

# Доступ к приватному методу через name mangling
obj._MyClass__private_method() # Выведет: Private method: The value is 30


Защищенные методы обозначаются одним подчёркиванием перед именем. Это указывает, что метод предназначен для внутреннего использования в классе и его подклассах, но не обеспечивает строгих ограничений доступа.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Как создать анонимную функцию в Python?
Anonymous Quiz
6%
def
79%
lambda
12%
anon
3%
func
Как в классах хранятся атрибуты и методы ?
Спросят с вероятностью 3%

Атрибуты и методы классов хранятся в специальном словаре, который называется dict. Этот словарь содержит все атрибуты и методы экземпляра или класса.

Атрибуты и методы экземпляра

Когда мы создаем объект класса, для него создается словарь атрибутов экземпляра, где хранятся все данные, специфичные для этого объекта.

Пример
class MyClass:
class_attr = 42

def __init__(self, value):
self.instance_attr = value

def instance_method(self):
return f"Instance attribute: {self.instance_attr}"

@classmethod
def class_method(cls):
return f"Class attribute: {cls.class_attr}"

# Создание экземпляра класса
obj = MyClass(10)

# Доступ к словарю атрибутов экземпляра
print(obj.__dict__) # Выведет: {'instance_attr': 10}

# Доступ к атрибуту экземпляра
print(obj.instance_attr) # Выведет: 10

# Вызов метода экземпляра
print(obj.instance_method()) # Выведет: Instance attribute: 10


Атрибуты и методы класса


Хранятся в словаре класса. Этот словарь можно получить через атрибутnt(obj.insсамого класса.


Пример
# Доступ к словарю атрибутов класса
print(MyClass.__dict__)

# Выведет что-то подобное (фактический вывод может варьироваться):
# {
# '__module__': '__main__',
# 'class_attr': 42,
# '__init__': <function MyClass.__init__ at 0x7f941d8e0d30>,
# 'instance_method': <function MyClass.instance_method at 0x7f941d8e0dc0>,
# 'class_method': <classmethod object at 0x7f941d8e0d90>,
# '__dict__': <attribute '__dict__' of 'MyClass' objects>,
# '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
# '__doc__': None
# }

# Доступ к атрибуту класса
print(MyClass.class_attr) # Выведет: 42

# Вызов метода класса
print(MyClass.class_method()) # Выведет: Class attribute: 42


Динамическое добавление атрибутов и методов

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

Пример для экземпляра

obj.new_attr = "I am new!"
print(obj.__dict__) # Выведет: {'instance_attr': 10, 'new_attr': 'I am new!'}
print(obj.new_attr) # Выведет: I am new!


Пример для класса
def new_class_method(cls):
return "This is a new class method"

MyClass.new_class_method = classmethod(new_class_method)

print(MyClass.new_class_method()) # Выведет: This is a new class method


Атрибуты и методы экземпляра хранятся в словаре __dict__ экземпляра, а атрибуты и методы класса — в словаре с вероятнкласса. Эти словари позволяют динамически добавлять и изменять атрибуты и методы.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Чем отличается атрибут класса от атрибута метода ?
Спросят с вероятностью 3%

Важно различать атрибуты класса и атрибуты экземпляра, так как они управляют различными аспектами хранения данных и поведения объектов.

Атрибуты класса (class attributes)

Принадлежат самому классу и одинаковы для всех экземпляров этого класса. Они объявляются внутри класса, но вне каких-либо методов. Эти атрибуты могут быть доступны как через сам класс, так и через его экземпляры.

Пример:
class MyClass:
class_attr = 42 # Атрибут класса

def __init__(self, value):
self.instance_attr = value # Атрибут экземпляра

def instance_method(self):
return f"Instance attribute: {self.instance_attr}"

@classmethod
def class_method(cls):
return f"Class attribute: {cls.class_attr}"

# Доступ к атрибуту класса через класс
print(MyClass.class_attr) # Выведет: 42

# Создание экземпляра класса
obj1 = MyClass(10)
obj2 = MyClass(20)

# Доступ к атрибуту класса через экземпляры
print(obj1.class_attr) # Выведет: 42
print(obj2.class_attr) # Выведет: 42

# Изменение атрибута класса
MyClass.class_attr = 100
print(obj1.class_attr) # Выведет: 100
print(obj2.class_attr) # Выведет: 100


Атрибуты экземпляра (instance attributes)

Принадлежат конкретному объекту (экземпляру) класса. Они обычно инициализируются в методе __init__ и могут иметь разные значения для разных экземпляров.

Пример:
class MyClass:
def __init__(self, value):
self.instance_attr = value # Атрибут экземпляра

def instance_method(self):
return f"Instance attribute: {self.instance_attr}"

# Создание экземпляров класса
obj1 = MyClass(10)
obj2 = MyClass(20)

# Доступ к атрибутам экземпляров
print(obj1.instance_attr) # Выведет: 10
print(obj2.instance_attr) # Выведет: 20

# Изменение атрибутов экземпляров
obj1.instance_attr = 15
print(obj1.instance_attr) # Выведет: 15
print(obj2.instance_attr) # Выведет: 20


Основные различия

1️⃣Принадлежность:
Атрибуты класса принадлежат самому классу и одинаковы для всех его экземпляров.
Атрибуты экземпляра принадлежат конкретному объекту и могут различаться между экземплярами.

2️⃣Инициализация:
Атрибуты класса определяются в теле класса вне методов.
Атрибуты экземпляра обычно инициализируются в методе
ass(10)
ob
или других методах экземпляра.

3️⃣Доступ:
Атрибуты класса могут быть доступны как через класс, так и через его экземпляры.
Атрибуты экземпляра доступны только через экземпляры.

4️⃣Обновление:
Изменение атрибута класса через класс влияет на все экземпляры, но изменение атрибута экземпляра затрагивает только конкретный экземпляр.

Пример совмещения атрибутов класса и экземпляра
class MyClass:
class_attr = "Class attribute"

def __init__(self, instance_value):
self.instance_attr = instance_value

def show_attrs(self):
return f"{self.instance_attr} | {MyClass.class_attr}"

# Создание экземпляров класса
obj1 = MyClass("Instance 1")
obj2 = MyClass("Instance 2")

# Доступ к атрибутам через экземпляры
print(obj1.show_attrs()) # Выведет: Instance 1 | Class attribute
print(obj2.show_attrs()) # Выведет: Instance 2 | Class attribute

# Изменение атрибута класса
MyClass.class_attr = "New Class attribute"
print(obj1.show_attrs()) # Выведет: Instance 1 | New Class attribute
print(obj2.show_attrs()) # Выведет: Instance 2 | New Class attribute

# Изменение атрибута экземпляра
obj1.instance_attr = "Updated Instance 1"
print(obj1.show_attrs()) # Выведет: Updated Instance 1 | New Class attribute


Атрибуты класса принадлежат классу и одинаковы для всех его экземпляров. Атрибуты экземпляра принадлежат конкретным объектам и могут отличаться между экземплярами. Объявляются в теле класса, тогда как атрибуты экземпляра обычно инициализируются в методе
alue  # Ат


👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какой из этих двух классов вызывается первым ?
Спросят с вероятностью 3%

Вопрос о том, какой из двух классов вызывается первым, предполагает ситуацию с наследованием и порядком вызова конструкторов (или методов) в иерархии классов. Порядок вызова конструкторов и методов определяется в первую очередь методом разрешения порядка (MRO — Method Resolution Order). Это правило особенно важно в случае множественного наследования.

Рассмотрим пример с двумя классами, где один наследуется от другого:
class A:
def __init__(self):
print("Constructor of A")

class B(A):
def __init__(self):
print("Constructor of B")
super().__init__()

# Создание экземпляра класса B
b = B()


Порядок вызова

1️⃣Когда создается объект класса B, сначала вызывается его конструктор __init__.
2️⃣Внутри конструктора B вызов super().__init__() вызывает конструктор базового класса A.

Вывод программы будет:
Constructor of B
Constructor of A


Это означает, что сначала вызывается конструктор B, а затем конструктор A.

Метод разрешения порядка (MRO, Method Resolution Order)

Определяет порядок, в котором классы будут обрабатываться при наследовании. В Python этот порядок можно получить с помощью атрибута mro или функции mro().

Пример:
print(B.__mro__)


Вывод будет:
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)


Это означает, что порядок разрешения методов для класса B следующий:
1️⃣B
2️⃣A
3️⃣object

При множественном наследовании MRO становится еще важнее. Рассмотрим пример:
class A:
def __init__(self):
print("Constructor of A")

class B(A):
def __init__(self):
print("Constructor of B")
super().__init__()

class C(A):
def __init__(self):
print("Constructor of C")
super().__init__()

class D(B, C):
def __init__(self):
print("Constructor of D")
super().__init__()

# Создание экземпляра класса D
d = D()


Порядок вызова

Когда создается объект класса D, вызовы конструкторов происходят в соответствии с MRO для D.

Получение:

print(D.__mro__)


Вывод будет:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)


Вывод программы будет:
Constructor of D
Constructor of B
Constructor of C
Constructor of A


Это означает, что порядок вызова конструкторов следующий:
1️⃣D
2️⃣B
3️⃣C
4️⃣A

При создании объекта класса сначала вызывается конструктор самого класса, затем конструкторы его базовых классов в порядке, определенном MRO. В случае множественного наследования порядок вызова конструкторов определяется методом разрешения порядка (MRO).

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какая разница между методами str и repr ?
Спросят с вероятностью 3%

Методы __str__ и repr используются для получения строкового представления объекта, но они имеют разные цели и используются в разных контекстах.

Метод str

Цель: Должен возвращать строковое представление объекта, которое будет понятным и удобным для пользователя.
Использование: Метод str используется функцией str() и при вызове print().
Предназначение: Для более дружественного и читаемого представления объекта.

Метод repr


Цель: Должен возвращать строку, которая официально представляет объект и, по возможности, позволяет воссоздать объект, если передать эту строку в eval().
Использование: Метод repr используется функцией repr() и вызывается интерактивной оболочкой Python для отображения объектов.
Предназначение: Для более точного и детализированного представления объекта, предназначенного для разработчиков.

Пример
class MyClass:
def __init__(self, value):
self.value = value

def __str__(self):
return f"MyClass with value {self.value}"

def __repr__(self):
return f"MyClass({self.value})"

obj = MyClass(10)

# Использование_(self):
print(str(obj)) # Выведет: MyClass with value 10
print(obj) # Выведет: MyClass with value 10 (так как print вызывает str)

# Использование
repr
print(repr(obj)) # Выведет: MyClass(10)


Основные различия

1️⃣Контекст использования:
__str__ предназначен для удобного представления объекта пользователю.
__repr__ предназначен для официального представления объекта, полезного для отладки и разработки.

2️⃣Вызываемые функции:
str() и print() используют str.
repr() и интерактивная оболочка Python используют repr.

3️⃣Содержимое строки:
__str__ возвращает удобочитаемую строку.
__repr__ возвращает строку, которая может включать больше технической информации и может использоваться для воссоздания объекта.

Пример с реализацией обоих методов
class Point:
def __init__(self, x, y):
self.x = x
self.y = y

def __str__(self):
return f"Point({self.x}, {self.y})"

def __repr__(self):
return f"Point({self.x}, {self.y})"

p = Point(1, 2)

# Использование
str
print(str(p))  # Выведет: Point(1, 2)
print(p) # Выведет: Point(1, 2)

# Использование
repr
print(repr(p)) # Выведет: Point(1, 2)


Дополнительный пример с различием междуstr__ и _и repr
class ComplexNumber:
def __init__(self, real, imag):
self.real = real
self.imag = imag

def __str__(self):
return f"{self.real} + {self.imag}i"

def __repr__(self):
return f"ComplexNumber({self.real}, {self.imag})"

c = ComplexNumber(3, 4)

# Использование
str
print(str(c))  # Выведет: 3 + 4i
print(c) # Выведет: 3 + 4i

# Использование
_ и repr и
print(repr(c)) # Выведет: ComplexNumber(3, 4)


Метод str возвращает понятное для пользователя строковое представление объекта, используемое функцией str() и print(). Метод repr возвращает официальное строковое представление объекта, используемое функцией repr() и интерактивной оболочкой, и часто предназначен для отладки.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Что такое абстракция ?
Спросят с вероятностью 3%

Абстракция
— это одна из основных концепций объектно-ориентированного программирования (ООП), наряду с инкапсуляцией, наследованием и полиморфизмом. Позволяет создавать упрощенные модели сложных систем, выделяя только те аспекты, которые являются важными для конкретной задачи, и скрывая детали реализации.

Основные аспекты

1️⃣Скрытие деталей реализации: Позволяет скрыть сложные детали реализации и показать только те части объекта, которые необходимы для его использования.
2️⃣Определение интерфейсов: Фокусируется на определении интерфейсов и методов, которые могут быть использованы для взаимодействия с объектом.
3️⃣Упрощение взаимодействия: Упрощает взаимодействие с объектами, предоставляя простой и понятный интерфейс.

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

Для создания абстрактных классов и методов в Python используется модуль abc (Abstract Base Classes).

Пример:
from abc import ABC, abstractmethod

class Animal(ABC):
@abstractmethod
def make_sound(self):
pass

class Dog(Animal):
def make_sound(self):
return "Bark"

class Cat(Animal):
def make_sound(self):
return "Meow"

# Создание экземпляров конкретных классов
dog = Dog()
cat = Cat()

print(dog.make_sound()) # Выведет: Bark
print(cat.make_sound()) # Выведет: Meow

# Попытка создания экземпляра абстрактного класса приведет к ошибке
# animal = Animal() # TypeError: Can't instantiate abstract class Animal with abstract methods make_sound


Основные компоненты


1️⃣Абстрактный класс (Animal): Определяет общие методы, которые должны быть реализованы в подклассах.
2️⃣Абстрактный метод (make_sound): Объявляется в абстрактном классе и должен быть реализован в любом конкретном подклассе.
3️⃣Конкретные классы (Dog и Cat): Реализуют абстрактный метод, предоставляя конкретную реализацию.

Преимущества

1️⃣Упрощение разработки: Позволяет сосредоточиться на высокоуровневом дизайне, не отвлекаясь на детали реализации.
2️⃣Повышение гибкости: Изменения в реализации могут быть сделаны без изменения интерфейсов, что облегчает модификацию и расширение кода.
3️⃣Улучшение читаемости: Абстрактные классы и методы делают код более понятным и структурированным, четко показывая, какие методы должны быть реализованы в подклассах.

Абстракция в ООП позволяет скрывать сложные детали реализации, предоставляя простой интерфейс для взаимодействия с объектами. Она упрощает разработку, улучшает читаемость кода и повышает его гибкость. Можно реализовать с помощью абстрактных классов и методов, используя модуль abc.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какие типы полиморфизма есть в python ?
Спросят с вероятностью 3%

Полиморфизм — это способность функции, метода или объекта работать с разными типами данных. Основные виды полиморфизма включают:

1️⃣Полиморфизм подтипов (или полиморфизм наследования)
2️⃣Полиморфизм перегрузки (или параметрический полиморфизм)
1️⃣Полиморфизм утиной типизации (или полиморфизм по интерфейсу)

Полиморфизм подтипов (наследование)

Этот тип позволяет использовать объект любого класса, который является подклассом базового класса. Это достигается с помощью наследования. Метод, определенный в базовом классе, может быть переопределен в подклассах.

Пример

class Animal:
def make_sound(self):
pass

class Dog(Animal):
def make_sound(self):
return "Bark"

class Cat(Animal):
def make_sound(self):
return "Meow"

def make_animal_sound(animal):
print(animal.make_sound())

# Использование полиморфизма подтипов
dog = Dog()
cat = Cat()

make_animal_sound(dog) # Выведет: Bark
make_animal_sound(cat) # Выведет: Meow


Полиморфизм перегрузки (параметрический полиморфизм)


Нет явной поддержки перегрузки функций и методов, как в некоторых других языках программирования. Однако, параметрический полиморфизм можно достичь через использование аргументов с значениями по умолчанию, переменным количеством аргументов, а также с помощью таких структур данных, как списки и словари.

Пример
def add(a, b):
return a + b

print(add(1, 2)) # Выведет: 3 (работает с числами)
print(add("Hello, ", "World!")) # Выведет: Hello, World! (работает со строками)


В этом примере функция add работает с разными типами данных благодаря динамической типизации в Python.

Полиморфизм утиной типизации (по интерфейсу)

Основывается на принципе "Если это выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, утка". Это означает, что не важно, к какому классу принадлежит объект, главное, чтобы он имел нужные методы или атрибуты.

Пример
class Duck:
def quack(self):
return "Quack"

class Person:
def quack(self):
return "I can imitate a duck"

def make_it_quack(duck_like):
print(duck_like.quack())

duck = Duck()
person = Person()

make_it_quack(duck) # Выведет: Quack
make_it_quack(person) # Выведет: I can imitate a duck


Полиморфизм функций высшего порядка

Можно также применять полиморфизм с функциями высшего порядка — функциями, которые принимают другие функции в качестве аргументов или возвращают функции в качестве результата.

Пример
def apply_function(func, value):
return func(value)

def square(x):
return x * x

def double(x):
return x * 2

print(apply_function(square, 4)) # Выведет: 16
print(apply_function(double, 4)) # Выведет: 8


1️⃣Полиморфизм подтипов: Использование объектов подклассов через базовый класс.
2️⃣Полиморфизм перегрузки: Функции и методы могут работать с разными типами данных, хотя явной перегрузки в Python нет.
3️⃣Полиморфизм утиной типизации: Объекты используются на основе наличия необходимых методов или атрибутов, независимо от их класса.
4️⃣Функции высшего порядка: Функции, принимающие или возвращающие другие функции, могут работать с разными типами функций.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как создать итератор из коллекции ?
Спросят с вероятностью 3%

Итератор — это объект, который позволяет перебирать элементы коллекции один за другим. Он реализует метод __next__(), который возвращает следующий элемент коллекции или вызывает исключение StopIteration, если элементы коллекции закончились.

Рассмотрим простой пример с использованием списка:
# Создание списка
my_list = [1, 2, 3, 4, 5]

# Создание итератора из списка
my_iterator = iter(my_list)

# Перебор элементов с помощью итератора
print(next(my_iterator)) # Выведет: 1
print(next(my_iterator)) # Выведет: 2
print(next(my_iterator)) # Выведет: 3
print(next(my_iterator)) # Выведет: 4
print(next(my_iterator)) # Выведет: 5

# Следующий вызов next() вызовет исключение StopIteration
# print(next(my_iterator)) # StopIteration


Итераторы можно создавать из различных коллекций, таких как строки, кортежи, множества и словари.

Примеры:

С строкой
my_string = "hello"
my_iterator = iter(my_string)

print(next(my_iterator)) # Выведет: h
print(next(my_iterator)) # Выведет: e
print(next(my_iterator)) # Выведет: l
print(next(my_iterator)) # Выведет: l
print(next(my_iterator)) # Выведет: o


С кортежем
my_tuple = (10, 20, 30)
my_iterator = iter(my_tuple)

print(next(my_iterator)) # Выведет: 10
print(next(my_iterator)) # Выведет: 20
print(next(my_iterator)) # Выведет: 30


С множеством
my_set = {1, 2, 3}
my_iterator = iter(my_set)

print(next(my_iterator)) # Выведет один из элементов множества (порядок не гарантирован)
print(next(my_iterator)) # Выведет другой элемент множества
print(next(my_iterator)) # Выведет оставшийся элемент множества


Со словарём

my_dict = {'a': 1, 'b': 2, 'c': 3}
my_iterator = iter(my_dict)

print(next(my_iterator)) # Выведет: a
print(next(my_iterator)) # Выведет: b
print(next(my_iterator)) # Выведет: c


Создание пользовательского итератора

Вы также можете создать собственный итератор, определив методы __iter__() и __next__() в своем классе.

Пример пользовательского итератора
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end

def __iter__(self):
return self

def __next__(self):
if self.current < self.end:
self.current += 1
return self.current - 1
else:
raise StopIteration

# Использование пользовательского итератора
my_iter = MyIterator(1, 5)

for num in my_iter:
print(num) # Выведет: 1 2 3 4


Для создания итератора из коллекции используйте функцию iter(). Итераторы позволяют перебирать элементы коллекции один за другим с помощью метода next(). Вы также можете создать собственный итератор, реализовав методы __iter__() и __next__() в своем классе.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как сделать класс, который будет поддерживать протокол итератора ?
Спросят с вероятностью 3%

Чтобы сделать класс, который поддерживает протокол итератора, нужно реализовать два метода: __iter__() и __next__(). Метод __iter__() должен возвращать сам итератор (обычно это сам объект), а метод __next__() должен возвращать следующий элемент последовательности или выбрасывать исключение StopIteration, когда элементы заканчиваются.

Вот пример класса, который реализует протокол итератора:
class MyRange:
def __init__(self, start, end):
self.start = start
self.end = end
self.current = start

def __iter__(self):
return self

def __next__(self):
if self.current < self.end:
current = self.current
self.current += 1
return current
else:
raise StopIteration

# Использование класса MyRange
my_range = MyRange(1, 5)

for number in my_range:
print(number) # Выведет: 1 2 3 4


Объяснение

1️⃣Конструктор __init__:
Инициализирует начальное значение (start), конечное значение (end) и текущее значение (current), которое будет изменяться при итерации.

2️⃣Метод iter:
Возвращает сам итератор, то есть self.

3️⃣Метод next:
Проверяет, достигло ли текущее значение (self.current) конечного значения (self.end).
Если текущее значение меньше конечного, метод увеличивает текущее значение на 1 и возвращает предыдущее текущее значение.
Если текущее значение больше или равно конечному, выбрасывается исключение StopIteration.

Можно также создать более сложный итератор, например, для перебора элементов списка.
class MyListIterator:
def init(self, my_list):
self.my_list = my_list
self.index = 0

def iter(self):
return self

def next():
if self.index < len(self.my_list):
result = self.my_list[self.index]
self.index += 1
return result
else:
raise StopIteration

# Использование класса MyListIterator
my_list = [10, 20, 30, 40]
my_iterator = MyListIterator(my_list)

for item in my_iterator:
print(item) # Выведет: 10 20 30 40


Обработка итераций с вложенными циклами

Иногда может потребоваться использовать итератор в контексте вложенных циклов или других структур. В этом случае итератор должен поддерживать повторное использование.
class ResettableRange:
def __init__(self, start, end):
self.start = start
self.end = end
self.current = start

def __iter__(self):
self.current = self.start # Сброс текущего значения при начале новой итерации
return self

def __next__(self):
if self.current < self.end:
current = self.current
self.current += 1
return current
else:
raise StopIteration

# Использование класса ResettableRange
resettable_range = ResettableRange(1, 5)

# Первый цикл
for number in resettable_range:
print(number) # Выведет: 1 2 3 4

# Второй цикл
for number in resettable_range:
print(number) # Снова выведет: 1 2 3 4


Чтобы создать класс, поддерживающий протокол итератора, нужно реализовать методы iter() и next(). Метод iter() возвращает сам итератор, а метод next() возвращает следующий элемент или выбрасывает StopIteration, когда элементы заканчиваются.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1096 вопроса на Python разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какая библиотека Python обычно используется для работы с векторными и матричными операциями?
Anonymous Quiz
17%
pandas
25%
matplotlib
53%
numpy
5%
scipy