2013-02-15 8 views
5

Rozważmy klasę z „prywatny” metody takie jak:override „prywatny” metody w Pythonie

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

Kiedy próbuję podklasy Foo i sposobu obejścia __method, można zauważyć, że Foo.__method nadal nazywa, zamiast MoreFoo.__method.

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

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

Jaki byłby sposób na zastąpienie takiej metody?

+0

http://stackoverflow.com/questions/1301346/the-meaning-of-----double-underscore-before-an-object-name-in-python – tacaswell

+0

Ciekawe, gdzie Czy wpadliście na pomysł, że jest to odpowiednik zmiennej prywatnej? To naprawdę złe nieporozumienie i widzę to cały czas, nie mając pojęcia, skąd pochodzi. –

+1

@Lattyware - Myślę, że pochodzi z sekcji o dokumentach o nazwie "Zmienne prywatne i lokalne klasy referencyjne". Mówi się, że nie ma żadnych zmiennych prywatnych ... ale to, co podwójnie podkreślisz, jest najbliższe - "Ponieważ istnieje ważna przypadek użycia dla prywatnych członków klasy (a mianowicie, aby uniknąć kolizji nazwisk z nazwami określonymi przez podklasy), jest ograniczone wsparcie dla takiego mechanizmu, ... " – mgilson

Odpowiedz

16

punkt z użyciem podwójnie podkreślenia nazwy konwencji jest zapobieganie podklasy z (przypadkowo) przesłanianie metody.

Jeśli masz i masz zastąpić go, ktoś popełnił poważny błąd w konstrukcji klasy. Można to zrobić jeszcze, nazywając swój obiekt tak:

def _Foo__method(self): 

gdzie można poprzedzić nazwę metody z jednym więcej podkreślenia i classname określającą (a więc w tym przypadku ustalonej z _Foo). Proces zmiany nazw metod i atrybutów z podwójnym podkreśleniem nazywa się private name mangling.

Jeśli chcesz zdefiniować metodę "prywatną", która jest nadal możliwa do zastąpienia w podklasie, zamiast tego zwykle używasz nazw z jednym podkreśleniem (def _method(self):).

Ze względu na jego dynamiczną naturę, prawie nic w Pythonie nie jest prawdziwie prywatne; przy odrobinie introspekcji można osiągnąć prawie wszystko.

8

Przedrostek podwójnego podkreślenia wywołuje wymazywanie nazwy, jest to , a nie równoważne z metodą prywatną. Został zaprojektowany specjalnie w celu uniknięcia przesłonięcia przez podklasy (w tym przypadku nazwa metody staje się _Foo__method).

Jeśli masz szczegółów wdrażania, poprzedzić je jednym podkreślenia jest to powszechnie akceptowane znak metod Pythona, które nie mają być stosowane na zewnątrz. Nie ma tego egzekwowania, ponieważ nie działa w ten sposób Python.

+0

Mam świadomość, że to nie jest tak naprawdę prywatne, dlatego pisałem prywatnie między cudzysłowami. –

+0

@EnestA Nie chodzi tylko o to, że to * nie jest * prywatne, ponieważ nie jest w żaden sposób podobne lub porównywalne - pełni zupełnie inną rolę. –

+0

Miałem wrażenie, że można wywoływać metody, które zaczynają się od 2 podkreśleń "prywatny". Może nie jest. W tym przypadku przepraszam za używanie niewłaściwej terminologii. –

3

wierzę, że można zrobić coś takiego:

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

jako documented.

Każdy identyfikator postaci __spam (co najmniej dwóch czołowych podkreślenia najwyżej jeden wzdłużny podkreślenie) jest wzbudzający zastąpione _classname__spam, gdzie classname jest obecny nazwa klasy czołową podkreślenia (ów) odpędzono.

Ale projektanci oryginalnej klasy byli zdania, że ​​nie należy trzeba zrobić coś takiego jak co trudno zastąpić z podklasy jest cały sens podwójnego podkreślenia zacząć:

Nazwa mangling jest pomocne w pozwalając podklasy zastąpić metody bez zerwania intraclass wywołań metod.

+0

Technicznie powinno to zadziałać, ale przede wszystkim maskuje poważniejszy problem niewłaściwego użycia podwójnego podkreślenia. –

+0

@AndrewGorcester - Pewnie. Nie mówię, że to dobry pomysł. – mgilson

+0

Dzięki. Nie napisałem oryginalnej klasy. Chcę tylko zastąpić jedną z jego metod, która zaczyna się od dwóch podkreśleń. –