Dlaczego w Pythonie nie ma wyraźnych modyfikatorów dostępu:

28

Jeśli „jawne jest lepsze niż niejawne”, dlaczego nie ma w Pythonie jawnych modyfikatorów dostępu: publicznego, chronionego, prywatnego itp.?

Wiem, że chodzi o to, że programista powinien wiedzieć, co robić za pomocą podpowiedzi - nie trzeba używać „brutalnej siły”. Ale „enkapsulacja” lub „ukrywanie informacji” IMO to nie tylko po to, by ludzie byli z dala, to kwestia organizacji i struktury: twoje warstwy programistyczne powinny mieć samookreślające się, wyraźnie określone zakresy i granice, tak jak robią to systemy fizyczne.

Czy ktoś może mi pomóc tutaj z dokładnym wyjaśnieniem, dlaczego ograniczenia dostępu są sugerowane, a nie jawne w Pythonie, języku, który w przeciwnym razie wydaje się być idealny?

Edycja: Do tej pory widziałem 3 proponowane odpowiedzi i zdałem sobie sprawę, że moje pytanie składa się z 2 części:

  1. Dlaczego na przykład nie ma słów kluczowych

    private def myFunc(): 
        dostuff....

    zamiast IMO brzydkie i trudne do wpisania podkreślenia. Ale to nie jest ważny punkt.

  2. Co ważniejsze:

    Dlaczego te modyfikatory dostępu są tylko „zaleceniami” lub wskazówkami i nie są egzekwowane. Trudno będzie później to zmienić? Bardzo łatwo jest zmienić „chroniony” na „publiczny” - a jeśli masz skomplikowany łańcuch dziedziczenia, który utrudnia, masz kiepski projekt - twój projekt powinien być udoskonalony, a nie polegać na funkcji językowej, która ułatwia pisanie źle skonstruowany kod.

    Po wprowadzeniu modyfikatorów dostępu kod jest automatycznie dzielony na przedziały - WIESZ, że niektóre segmenty są poza zakresem, więc nie musisz sobie z nimi radzić, chyba że i kiedy jest to konieczne. A jeśli twój projekt nie jest dobry, a ty ciągle przemieszczasz rzeczy do różnych zakresów, język może pomóc ci posprzątać.

Mimo że uwielbiam Python, uważam, że ten drugi punkt jest poważnym brakiem. I nie znalazłem jeszcze na to dobrej odpowiedzi.

Wektor
źródło
możliwy duplikat specyfikatorów Access w Pythonie: ... który został zamknięty, ponieważ nie jest konstruktywny.
Frank Shearar,
2
@Frank, to jest ponowne pytanie tego pytania, aby spróbować być bardziej konstruktywnym. Poszedłem dalej i usunąłem pierwotne pytanie.
@ Mark Trapp: Ah OK. Dziękuję za wyjaśnienie. Nie widzę, jak odwołać mój głos za zamknięciem.
Frank Shearar,
@Frank Starzeje się sam.
Adam Lear
problem private def whateverpolega na tym, że class x: def whatever(self): passjest to skrót do class x: pass; x.whatever = lambda self: pass, więc w zasadzie potrzebujesz prywatnego modyfikatora do przypisania
keppla

Odpowiedzi:

22

„Jawne jest lepsze niż niejawne” to tylko jedna z maksym filozofii projektowania Pythona. Jest też „proste jest lepsze niż złożone”. I chociaż nie ma go w Zen Pythona, „Wszyscy zgadzamy się tutaj, dorośli” to coś innego.

Ta druga zasada jest chyba najważniejsza. Kiedy projektuję klasę, mam pojęcie, w jaki sposób będzie ona wykorzystywana. Ale nie mogę przewidzieć wszystkich możliwych zastosowań. To może być to, że niektóre przyszłe wykorzystanie mojego kodu wymaga dostępu do zmiennych Myślałam jako prywatne. Dlaczego miałbym utrudniać, a nawet uniemożliwiać dostęp do nich, jeśli przyszły programista (a nawet przyszły ja) potrzebuje ich? Najlepszym rozwiązaniem jest oznaczenie ich ostrzeżeniem - jak zauważa Joonas, standardowy prefiks podkreślenia jest standardem - że są wewnętrzne i mogą ulec zmianie; ale całkowity zakaz dostępu wydaje się niepotrzebny.

Daniel Roseman
źródło
1
„Proste jest lepsze niż skomplikowane” i „Wszyscy zgadzamy się tutaj, że dorośli” właśnie dlatego Smalltalk nie ma modyfikatorów dostępu. Umieszczenie metody w kategorii „prywatnej” jest wskazówką, że powinieneś pomyśleć trzy razy przed użyciem i nie więcej.
Frank Shearar,
@Frank: „Umieszczenie metody w kategorii„ prywatnej ”jest wskazówką, że powinieneś pomyśleć trzy razy przed użyciem, i nigdy więcej” Dla mnie oznacza to po prostu, że nie muszę się o to martwić, gdy nie mam do czynienia z tym.
Wektor
8
Istnieje dobry powód, dla którego zabrania się dostępu do prywatnych członków: ponieważ może to złamać niezmienniki klasowe. Jeśli nie możesz pisać członków prywatnych, nie możesz być pewien, że twoja klasa zachowuje się poprawnie.
svick
7
„Dlaczego miałbym utrudniać, a nawet uniemożliwiać dostęp do nich, jeśli przyszły programista (a nawet przyszły ja) potrzebuje ich?” Ponieważ jedną z podstawowych zasad projektowania jest rozdział między interfejsem (co zapewnia kawałek kodu) a implementacją (jak to zapewnia). Hermetyzacja służy do zmniejszenia złożoności kodu poprzez zmniejszenie zależności między różnymi częściami kodu. Zatem publiczne i prywatne są używane właśnie w celu uproszczenia kodu, pozwalając zobaczyć tylko to, co jest potrzebne.
Giorgio
3
Nie mogę się więcej zgodzić. Modyfikatory dostępu promują dwa prawdopodobnie najlepiej rozumiane pojęcia w celu ograniczenia złożoności dużego oprogramowania: Encapsulation and Separation of Concerns. Nieudzielenie żadnego z nich oznacza po prostu, że python nie jest dobrym językiem OOP ani nie nadaje się do budowania dużego oprogramowania i nie ma w tym nic złego. Ale uzasadniając brak takich funkcji typowymi hobbystycznymi argumentami, takimi jak „Po co zwiększać złożoność, gdy nie jest potrzebna?” jest po prostu zły.
Daniel Shin
10

Podejrzewam, że głównym powodem braku modyfikatorów dostępu jest prostota

Jak mówisz, nie chodzi o trzymanie ludzi z dala, chodzi o organizację, więc głównym punktem „prywatnego” jest to, że wysyła wiadomość do użytkowników twojego interfejsu API „nie pisz kodu, który zależy od tego”.

Trywialne jest stwierdzenie „zgodnie z konwencją, _x lub __x nie powinny być używane poza klasą”, ale w dynamicznym modelu obiektowym Pythona trudno byłoby nawet wymyślić notację.

class ActiveRow(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

jak zauważyć dostępność?

To chyba kompromis. Jeśli ściśle nie możesz z tym żyć, sugerowałbym rubin, który ma podobny poziom abstrakcji i dynamiki, ale ma model obiektowy, który pozwala na modyfikację dostępu.

keppla
źródło
8
Myślę, że to prawda, ale IMO jest okropne. Dla języka, który wykorzystuje elegancję i czytelność jako punkty sprzedaży, pisząc __method__ jest dość ohydny i tępy.
jiggy
2
to nie jest konwencja, __x__to „magia” (tj. metody wywoływane w celu umożliwienia integracji językowej, takie jak przeciążenie operatora, iterowalność itp.). Konwencja jest _x.
keppla,
6
Przepraszam, wciąż kręcę się po Pythonie. Bardzo się staram to polubić, ale takie rzeczy prowadzą trochę do szału. Zwłaszcza teraz, gdy muszę pamiętać znaczenie, jak wiele znaków podkreśla metoda. Z punktu widzenia OP wydaje się, że wyraźne modyfikatory byłyby bardziej jasne. Podsumowanie jest świetne, ale nie może przeważyć jasności. Poświęcasz 10 razy więcej wysiłku na utrzymanie kodu niż na jego budowanie.
jiggy
2
Mój przykład nie miał na celu pokazania różnych liczb podkreśleń, użycie __init__było przypadkowe. Przykład ustawia niektóre właściwości obiektu, które nie są znane w czasie kompilacji, więc wyraźny modyfikator dostępu nie pomoże.
keppla
5
@jiggy: „Tak bardzo staram się to lubić”. Próbowałem przez 2 lata - potem się poddałem. :-( Wygląda na język skryptowy, który został zhakowany, by zachowywać się trochę jak prawdziwy język OOP. Nie wyobrażam sobie pisania dużej, złożonej aplikacji w Pythonie, która była dobrze zaprojektowana i czytelna. Jak powiedziałeś „Spędzasz 10 razy więcej wysiłku utrzymywanie kodu niż budowanie go. Proste koncepcje OOP i bezpieczne typy wymagają szalonych hacków i obejść.
Vector
8

Konwencja Pythona polega na użyciu prefiksu podkreślenia dla członków chronionych / prywatnych.

Konwencja ta, kiedy następuje, jest faktycznie taki sam jak modyfikatory dostępu, z wyjątkiem: 1) zobaczysz bezpośrednio od uczestnika nazwy czy to publicznych, czy nie, i 2), które mogą złamać „hermetyzacji”, jeśli naprawdę chcesz (może to być uzasadnione np. podczas testowania; w niektórych innych językach będziesz musiał użyć refleksji == więcej kodu).

Ostatecznie jest to kwestia gustu, ale jeśli możesz zrobić to samo (z nieco większą elastycznością) bez specjalnych słów kluczowych, język będzie mniejszy, a kod będzie bardziej zwięzły, co na ogół jest dobrą rzeczą.

Joonas Pulakka
źródło
2
„jeśli możesz zrobić to samo (z nieco większą elastycznością) bez specjalnych słów kluczowych, język będzie mniejszy, a kod będzie bardziej zwięzły”. Moim zdaniem, ogólnie nie jest to prawdą. (Nawet jeśli może tak być w przypadku specjalnego modyfikatora dostępu)
BenjaminB,