Part 9

Область видимости методов

Методы, определенные внутри класса, можно скрывать ровно так же, как атрибуты в предыдущем разделе. Если метод начинается с двух подчеркиваний __, он не доступен клиенту напрямую.

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

Приватный метод можно использовать внутри класса так же, как любой другой метод, конечно, не забывая добавить префикс 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)]

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

Loading
Вы дошли до конца этого раздела! Перейти к следующему разделу:

Текущие баллы можно посмотреть в синем индикаторе в правом нижнем углу страницы.