Область видимости методов
Методы, определенные внутри класса, можно скрывать ровно так же, как атрибуты в предыдущем разделе. Если метод начинается с двух подчеркиваний __, он не доступен клиенту напрямую.
Итак, техника одна и та же и для методов, и для атрибутов, но случаи использования обычно немного отличаются. Приватные атрибуты часто идут в паре с методами-геттерами и методами-сеттерами, которые управляют доступом к ним. Приватные методы, с другой стороны, обычно предназначены только для внутреннего использования, как вспомогательные методы для процессов, о которых клиенту не нужно знать.
Приватный метод можно использовать внутри класса так же, как любой другой метод, конечно, не забывая добавить префикс self. Ниже приведен простой класс, представляющий получателя электронных писем. Он включает приватный вспомогательный метод д ля проверки, что адрес электронной почты имеет допустимый формат:
class Recipient:
def __init__(self, name: str, email: str):
self.__name = name
if self.__check_email(email):
self.__email = email
else:
raise ValueError("The email address is not valid")
def __check_email(self, email: str):
# A simple check: the address must be over 5 characters long
# and contain a dot and an @ character
return len(email) > 5 and "." in email and "@" in emailПопытка вызвать приватный метод напрямую вызывает ошибку:
peter = Recipient("Peter Emailer", "peter@example.com")
peter.__check_email("someone@example.com")AttributeError: 'Recipient' object has no attribute '__check_email'
Внутри класса к методу можно обращаться обычным образом, и имеет смысл использовать его также для установки нового значения адреса. Добавим методы-геттеры и методы-сеттеры для адреса электронной почты:
class Recipient:
def __init__(self, name: str, email: str):
self.__name = name
if self.__check_email(email):
self.__email = email
else:
raise ValueError("The email address is not valid")
def __check_email(self, email: str):
# A simple check: the address must be over 5 characters long
# and contain a dot and an @ character
return len(email) > 5 and "." in email and "@" in email
@property
def email(self):
return self.__email
@email.setter
def email(self, email: str):
if self.__check_email(email):
self.__email = email
else:
raise ValueError("The email address is not valid")Нужен ли мне приватный метод?
В следующем примере класс DeckOfCards — это модель колоды из 52 карт. Он содержит вспомогательный метод __reset_deck, который создает новую перемешанную колоду карт. На данный момент приватный метод вызывается только в методе-конструкторе, поэтому реализацию, вероятно, можно было бы поместить прямо в конструктор. Однако использование отдельного метода делает код легче для чтения и также позволяет позже обращаться к этой функциональности из других методов, если это понадобится.
from random import shuffle
class DeckOfCards:
def __init__(self):
self.__reset_deck()
def __reset_deck(self):
self.__deck = []
# Add all 52 cards to the deck
suits = ["spades", "hearts", "clubs", "diamonds"]
for suit in suits:
for number in range(1, 14):
self.__deck.append((suit, number))
# Shuffle the deck
shuffle(self.__deck)
def deal(self, number_of_cards: int):
hand = []
# Move the top cards in the deck to the hand
for i in range(number_of_cards):
hand.append(self.__deck.pop())
return handПроверим класс:
deck = DeckOfCards()
hand1 = deck.deal(5)
print(hand1)
hand2 = deck.deal(5)
print(hand2)Поскольку руки генерируются случайно, следующее — лишь пример того, что может быть выведено:
[('spades', 7), ('spades', 11), ('hearts', 7), ('diamonds', 3), ('spades', 4)] [('clubs', 8), ('spades', 12), ('diamonds', 13), ('clubs', 11), ('spades', 10)]
Приватные методы в целом встречаются реже, чем приватные атрибуты. Как практическое правило, метод следует скрывать всякий раз, когда клиенту не нужно обращаться к нему напрямую. Это особенно важно, когда клиент может нарушить целостность объекта, вызвав такой метод.
Текущие баллы можно посмотреть в синем индикаторе в правом нижнем углу страницы.