переопределить "частный" метод в Python

рассмотрим класс с "частным" методом, таким как:

class Foo(object):
    def __init__(self):
        self.__method()
    def __method(self):
        print('42')

когда я пытаюсь подкласс Foo и переопределить метод __method, видно, что Foo.__method по-прежнему называется, а не MoreFoo.__method.

class MoreFoo(Foo):
    def __method(self):
        print('41')

>>> MoreFoo()
42
<__main__.MoreFoo object at 0x7fb726197d90>

каков был бы способ переопределить такой метод?

3 ответов


на точка использование соглашения о двойном подчеркивании имен-это предотвращение (случайного) переопределения подклассов методом.

Если вы есть чтобы переопределить его в любом случае, кто-то сделал серьезную ошибку дизайна класса. Вы можете сделать это еще, назвав свой объект так:

def _Foo__method(self):

где вы префикс имя метода с еще одним подчеркиванием и определяющим classname (так что в этом случае с префиксом _Foo). Процесс переименования методы и атрибуты с двойным подчеркиванием называются частное имя коверкая.

Если вы хотите определить "частный" метод, который по-прежнему переопределяется в подклассе, вы обычно придерживаетесь имен с одним подчеркиванием (def _method(self):).

из-за его динамической природы почти ничего в Python не является действительно частным; с небольшим самоанализом почти все может быть достигнуто.


двойной префикс подчеркивания вызывает искажение имени, это не эквивалент частного метода. Он специально разработан, чтобы избежать переопределения подклассами (и в этом случае имя метода становится _Foo__method).

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


Я считаю, что вы сделали бы что-то вроде:

class MoreFoo(Foo):
    def _Foo__method(self):
        print('41')

as документирована.

любой идентификатор формы __spam (не менее двух ведущих подчеркиваний, не более одного завершающего подчеркивания) текстуально заменяется на _classname__spam, где classname - это текущее имя класса с начальным подчеркиванием(подчеркиванием).

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

name mangling полезно для разрешения подклассов переопределять методы без нарушения внутриклассных вызовов методов.