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

Сайт: easyoffer.ru
Реклама: @easyoffer_adv
Download Telegram
Как выражена инкапсуляция в python ?
Спросят с вероятностью 3%

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

Соглашения об именовании

1️⃣Приватные атрибуты и методы:
В Python соглашение об именовании позволяет сделать атрибуты и методы приватными, что предотвращает их случайное использование вне класса.
Атрибуты и методы, начинающиеся с одного подчёркивания (_), считаются защищёнными и не должны использоваться вне класса или подклассов.
Атрибуты и методы, начинающиеся с двойного подчёркивания (__), подвергаются манглингу имён (name mangling), что делает их труднодоступными из вне класса.
class MyClass:
def __init__(self, value):
self._protected_value = value # Защищённый атрибут
self.__private_value = value # Приватный атрибут

def _protected_method(self):
print("This is a protected method.")

def __private_method(self):
print("This is a private method.")


Примеры использования

1️⃣Защищённые атрибуты и методы:
Они не предназначены для использования вне класса, но могут быть использованы в подклассах.
Их использование вне класса является плохой практикой, но технически возможно.
class SubClass(MyClass):
def access_protected(self):
print(self._protected_value)
self._protected_method()

instance = SubClass(10)
instance.access_protected()
# Выведет:
# 10
# This is a protected method.


2️⃣Приватные атрибуты и методы:
Они подвергаются манглингу имён, что делает их труднодоступными из вне класса.
Внешний доступ возможен, но с использованием специального синтаксиса, что считается плохой практикой.
class AnotherClass:
def __init__(self, value):
self.__private_value = value

def __private_method(self):
print("This is a private method.")

def access_private(self):
print(self.__private_value)
self.__private_method()

instance = AnotherClass(20)
instance.access_private()
# Выведет:
# 20
# This is a private method.

# Попытка доступа к приватному атрибуту извне
# print(instance.__private_value) # AttributeError

# Доступ с использованием манглинга имён (не рекомендуется)
print(instance._AnotherClass__private_value) # Выведет: 20


Свойства (Properties)


Предоставляют интерфейс для управления доступом к атрибутам и позволяют инкапсулировать логику доступа и изменения данных.
class MyClassWithProperty:
def __init__(self, value):
self._value = value

@property
def value(self):
return self._value

@value.setter
def value(self, new_value):
if new_value > 0:
self._value = new_value
else:
raise ValueError("Value must be positive")

instance = MyClassWithProperty(10)
print(instance.value) # Выведет: 10
instance.value = 20
print(instance.value) # Выведет: 20
# instance.value = -10 # ValueError: Value must be positive


Инкапсуляция достигается с помощью соглашений об именовании (одинарное подчёркивание для защищённых и двойное подчёркивание для приватных атрибутов и методов) и использования свойств для управления доступом к атрибутам. Это позволяет скрывать внутренние детали реализации и предоставлять контролируемый интерфейс для взаимодействия с объектами.

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

🔐 База собесов | 🔐 База тестовых
Какой метод декоратора property позволяет установить значение атрибута, при этом применяя дополнительные проверки или вычисления?
Anonymous Quiz
15%
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
13%
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 разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какая встроенная функция Python не существует?
Anonymous Quiz
46%
compile()
17%
exec()
25%
evaluate()
12%
getattr()
Чем отличается атрибут класса от атрибута метода ?
Спросят с вероятностью 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 разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какой декоратор из списка связан с многопоточностью?
Anonymous Quiz
8%
@classmethod
5%
@staticmethod
17%
@lru_cache()
70%
@synchronized
Какая разница между методами 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 разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых