Содержание

Инкапсуляция

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

Инкапсуляция в Python работает лишь на уровне соглашения между программистами о том, какие атрибуты являются общедоступными, а какие — внутренними.

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

class Person:

class Person:
    def __init__(self, name = 'Серега'):
        self.name = name
        self._age = 20  инкапсуляция на уровне соглашения protected, с одним нижним подеркиванием
    def _private(self):
        print("Это приватный метод, по соглашению!")
 
per = Person('Петя')
print(per._age) # Свойство доступно, но по соглашению его использовать не рекомендуется

Двойное подчеркивание в начале имени атрибута даёт большую защиту: атрибут становится недоступным по этому имени.

class Person:
    def __init__(self, name = 'Серега'):
        self.name = name
        self.__age = 20  # инкапсуляция типа private
 
    def __private(self):
        print("Это приватный метод!")
 
per = Person('Петя')
print(per.__age) # Свойство недоступно

Однако полностью это не защищает, так как атрибут всё равно остаётся доступным под именем _ИмяКласса__ИмяАтрибута:

print(per._Person__age) #Обход инкапсуляции, доступ к private свойтсву

Геттеры и Сеттеры

класс Person

class Person:
    def __init__(self, name = 'Серега'):
        self.name = name
        self.__age = 20 # инкапсуляция типа private
 
 
    def getAge(self):
        '''
        Доступ к private свойствам
 
        '''
        return self.__age
 
 
    def setAge(self, age):
        '''
        Доступ к private свойствам
 
        :param age передаваемый папраметр
        '''
        if age in range(20, 80):
            self.__age = age
        else:
            self.__age = 25

Использоание геттеров и сеттеров:

per = Person('Петя')
 
per.setAge(39)
print(per.getAge())

Результат:

>>> 39

Декортаторы в качетве геттеров и сеттеров

класс Person:

Декораторы необходисо создовать в определенной последовательности, сначала getter потом setter. В противном случае Python выкинет исключение и сообщение об ошибке.

class Person:
    def __init__(self, name = 'Серега'):
        self.name = name
        self.__age = 20 # инкапсуляция типа private
 
    @property
    def age(self):
        '''
        Декоратор
 
        :param age передаваемый папраметр
        '''
        return self.__age
 
    @age.setter
    def age(self, value):
        '''
        Декоратор
 
        :param value передаваемый папраметр
        '''
        self.__age = value

Обращение к закрытым своствам через декоратор

per.age = 36 # Обращение к закрытым свайствам через декоратор setter
print(per.age) # Обращение к закрытым свайствам через декоратор getter

Результат:

>>> 36

Наследование

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

>>> class Mydict(dict):
...     def get(self, key, default = 0):
...         return dict.get(self, key, default)
...
>>> a = dict(a=1, b=2)
>>> b = Mydict(a=1, b=2)

Класс Mydict ведёт себя точно так же, как и словарь, за исключением того, что метод get по умолчанию возвращает не None, а 0.

>>> b['c'] = 4
>>> print(b)
{'a': 1, 'c': 4, 'b': 2}
>>> print(a.get('v'))
None
>>> print(b.get('v'))
0

Полиморфизм

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

>>> 1 + 1
2
>>> "1" + "1"
'11'