2017-07-24 14 views
8
class A(object): 
    def __get(self): 
     pass 

    def _m(self): 
     return self.__get() 


class B(A): 
    def _m(self): 
     return str(self.__get()) 

print(A()._m()) 
print(B()._m()) 

Why print(A()._m()) wydruków None, ale print(B()._m()) podnosi AttributeError: 'B' object has no attribute '_B__get'?Pokój podkreślenia w Pythonie

Pomyślałem, że podwójne podkreślenie zapobiega przesłonięciu metody.

UPDATE

Piszesz, że __get jest prywatny.

Dlaczego więc działa następująca funkcja?

class A(object): 
    def __get(self): 
     pass 

    def _m(self): 
     return self.__get() 


class B(A): 
    pass 

print(A()._m()) 
print(B()._m()) 

Dlaczego ten kod nie budzi AttributeError i wydruki None dwa razy?

+2

[Naznaczanie nazwami] (https://docs.python.org/3/tutorial/classes.html#private-variables). Twoje wołanie do 'self .__ get()' w 'B' naprawdę nazywa' self._B__get() ', które nie istnieje. Jeśli nie chcesz tego zachowania, nie używaj wiodących podwójnych podkreśleń. – kindall

+0

Sprawdź [co oznacza znaczenie pojedynczego i podwójnego podkreślenia przed nazwą obiektu] (https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-a-single-and-a -double-underscore-before-an-object-name? rq = 1) i niektóre z powiązanych pytań, ponieważ istnieją pewne szczegółowe wyjaśnienia. – JGreenwell

+0

Ponowna aktualizacja: Ponieważ wywołujesz __get z metody zdefiniowanej w klasie A. Jest to całkowicie legalne w każdym języku, który obsługuje pojęcie prywatne - w rzeczywistości jest to najczęściej używany przypadek metod prywatnych. –

Odpowiedz

7

wiodących marek podwójne podkreślenia są private (czyli nie są dostępne dla klas pochodnych)

To nie jest niezawodne. Jest realizowany poprzez zniekształcanie nazwy. Python Documentation mówi:

Każdy identyfikator __spam postaci (co najmniej dwie wiodące podkreślenia co najwyżej jeden wleczonego podkreślenia) jest tekstowo zastąpione _classname__spam, gdzie classname jest obecna nazwa klasy z wiodącym podkreślenia (s) pozbawiony . To przekształcanie jest wykonywane bez względu na pozycję syntaktyczną identyfikatora, dzięki czemu można go używać do definiowania prywatnych instancji klasy i zmiennych klas, metod, zmiennych przechowywanych w globalizacjach, a nawet zmiennych przechowywanych w instancjach. prywatny do tej klasy na wystąpienia innych klas.

__get zatem faktycznie zniekształcone do _A__get w klasie A. Kiedy klasa B próbuje odwoływać __get, zostaje zniekształcone do _B__get który nie pasuje.

Innymi słowy __plugh zdefiniowany w klasie Xyzzy znaczy "chyba, że ​​pracujesz jako klasa Xyzzy, nie dotykaj __plugh".

+1

_ "Główne podwójne podkreślenia są" prywatne "(co oznacza, że ​​nie są dostępne dla klas pochodnych)" _ Nie rób tego. W Pythonie nie ma nazwy o nazwie private, te nazwy są (pseudoprivate), a nie prywatne. – direprobs

+0

@direprobs CEL wiodących podkreśleń jest ukrywanie symboli od everone z wyjątkiem klasy definiującej. W WIELU innych językach pojęcie to jest określane jako "prywatne". Dlatego użyłem pojedynczego słowa do pojęcia, które powinno być dobrze rozpoznane. Wyjaśniłem również szczegóły implementacji i wspomniałem o braku niezawodności. Jak inaczej proponowałbyś przekazanie koncepcji? –

+0

To jest problem.Słowo prywatne sugerowałoby na przykład prywatne, takie jak na przykład w Javie, do zmiennej nie można uzyskać dostępu spoza klasy. Powiedziałeś, że zmienna nie będzie dostępna dla klasy pochodnej, która jest absolutnie błędna. – direprobs