Python - Модификаторы доступа
Привет, стремящиеся к программированию на Python! Сегодня мы отправляемся в захватывающее путешествие в мир модификаторов доступа в Python. Не волнуйтесь, если вы новичок в программировании; я веду вас по этой концепции шаг за шагом, с множеством примеров и пояснений по пути. Поехали!
Модификаторы доступа в Python
В объектно-ориентированном программировании модификаторы доступа используются для управления видимостью и доступом к членам класса (атрибутам и методам). В то время как многие языки программирования имеют строгие модификаторы доступа, такие как public, private и protected, Python следует более спокойному подходу. Он следует философии, часто называемой "Мы все согласны здесь взрослые".
В Python у нас есть три типа модификаторов доступа:
- Public
- Protected
- Private
Давайте рассмотрим каждый из них с примерами.
Public Members
В Python все члены являются публичными по умолчанию. Это означает, что они могут быть доступны извне класса. Вот пример:
class Student:
def __init__(self, name, age):
self.name = name # Public attribute
self.age = age # Public attribute
def display_info(self): # Public method
print(f"Name: {self.name}, Age: {self.age}")
# Создание экземпляра Student
student1 = Student("Alice", 20)
# Доступ к публичным членам
print(student1.name) # Output: Alice
student1.display_info() # Output: Name: Alice, Age: 20
В этом примере name
, age
и display_info()
все являются публичными членами. Мы можем получить к ним доступ напрямую извне класса.
Protected Members
Защищенные члены обозначены префиксом с одной подчеркивательной (_). Они не являются действительно приватными и могут быть доступны извне класса, но это соглашение о том, что их следует рассматривать только для внутреннего использования.
class Employee:
def __init__(self, name, salary):
self._name = name # Protected attribute
self._salary = salary # Protected attribute
def _display_salary(self): # Protected method
print(f"{self._name}'s salary is ${self._salary}")
# Создание экземпляра Employee
emp1 = Employee("Bob", 50000)
# Доступ к защищенным членам (Обратите внимание: Это возможно, но не рекомендуется)
print(emp1._name) # Output: Bob
emp1._display_salary() # Output: Bob's salary is $50000
Хотя мы можем получить доступ к _name
, _salary
и _display_salary()
, обычно не рекомендуется делать это извне класса или его подклассов.
Private Members
Приватные члены обозначены префиксом с двумя подчеркивательными (__). Python выполняет изменение имен для этих членов, делая их сложнее (но не невозможно) доступными извне класса.
class BankAccount:
def __init__(self, account_number, balance):
self.__account_number = account_number # Private attribute
self.__balance = balance # Private attribute
def __display_balance(self): # Private method
print(f"Balance: ${self.__balance}")
def public_display(self):
self.__display_balance()
# Создание экземпляра BankAccount
account1 = BankAccount("123456", 1000)
# Попытка доступа к приватным членам
# print(account1.__account_number) # Это вызовет AttributeError
# account1.__display_balance() # Это также вызовет AttributeError
# Доступ к приватному методу через публичный метод
account1.public_display() # Output: Balance: $1000
В этом примере, __account_number
, __balance
и __display_balance()
являются приватными членами. Попытка доступа к ним напрямую извне класса вызовет AttributeError.
Изменение имен
Помните, когда я упомянул, что приватные члены в Python не являются действительно приватными? Это из-за механизма, называемого изменением имен. Когда вы создаете приватный член с двумя подчеркивательными, Python изменяет его имя внутри, чтобы сделать его сложнее доступным случайно.
Вот как это работает:
class NameManglingDemo:
def __init__(self):
self.__private_var = "Я приватный!"
demo = NameManglingDemo()
print(dir(demo))
# Output: [..., '_NameManglingDemo__private_var', ...]
# Доступ к приватной переменной с помощью измененного имени
print(demo._NameManglingDemo__private_var) # Output: Я приватный!
Как вы видите, Python переименовывает __private_var
в _NameManglingDemo__private_var
. Это изменение имен в действии!
Объект свойства Python
Функция property()
в Python является встроенной функцией, которая создает и возвращает объект свойства. Это способ добавить методы getter, setter и deleter к атрибутам класса.
Вот пример:
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
def get_fahrenheit(self):
return (self._celsius * 9/5) + 32
def set_fahrenheit(self, fahrenheit):
self._celsius = (fahrenheit - 32) * 5/9
fahrenheit = property(get_fahrenheit, set_fahrenheit)
# Использование свойства
temp = Temperature(25)
print(temp.fahrenheit) # Output: 77.0
temp.fahrenheit = 86
print(temp._celsius) # Output: 30.0
В этом примере fahrenheit
является свойством, которое позволяет нам получать и устанавливать температуру в Фаренгейтах, храня ее внутри в Цельсиях.
Методы Getter и Setter
Методы getter и setter используются для получения и установки значений атрибутов класса. Они предоставляют способ доступа и изменения приватных атрибутов, сохраняя энкapsulation.
Вот пример с использованием декоратора @property
, который является более питоническим способом реализации getter и setter:
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not isinstance(value, str):
raise ValueError("Имя должно быть строкой")
self._name = value
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if not isinstance(value, int) or value < 0:
raise ValueError("Возраст должен быть положительным целым")
self._age = value
# Использование getter и setter
person = Person("Charlie", 30)
print(person.name) # Output: Charlie
person.name = "David"
print(person.name) # Output: David
try:
person.age = -5
except ValueError as e:
print(e) # Output: Возраст должен быть положительным целым
В этом примере мы создали getter и setter для name
и age
. Методы setter включают валидацию, чтобы убедиться, что значения, которые устанавливаются, соответствуют определенным критериям.
Для подведения итогов рассмотренным методам, вот таблица в формате Markdown:
Метод | Описание | Пример |
---|---|---|
Public | Доступен из любого места | self.name |
Protected | Доступен внутри класса и подклассов (по соглашению) | self._name |
Private | Имя изменено для ограничения доступа | self.__name |
Property | Создает объект свойства | property(get_method, set_method) |
Getter | Метод для получения значения атрибута | @property |
Setter | Метод для установки значения атрибута | @attribute.setter |
И это всё! Мы покрыли модификаторы доступа в Python, изменение имен, объекты свойства и методы getter и setter. Помните, подход Python к управлению доступом больше основан на соглашениях и доверии, чем на строгих правилах. Когда вы продолжаете свое путешествие по Python, вы обнаружите, что эта гибкость позволяет писать чистый и читаемый код, сохраняя при этом способность реализовывать энкapsulation при необходимости.
Постарайтесь, будьте любознательными и счастливого кодирования!
Credits: Image by storyset