Jestem stosunkowo nowy w Pythonie, więc mam nadzieję, że nie zostały pominięte coś, ale tu idzie ...„Prywatna” właściwości atrybutów w Pythonie
Próbuję napisać moduł Pythona, a ja d utworzyć klasę z "prywatnym" atrybutem, który może (lub może "powinien") być modyfikowany tylko przez jedną lub więcej funkcji w module. Ma to na celu uczynienie modułu bardziej wytrzymałym, ponieważ ustawienie tego atrybutu poza tymi funkcjami może prowadzić do niepożądanego zachowania. Na przykład może mam:
- klasy, która przechowuje wartości X i Y dla wykresu punktowego,
Data
- funkcji do odczytu wartości X i Y z pliku i przechowywać je w klasie,
read()
- funkcja je wykreślić,
plot()
W tym przypadku wolałbym, jeśli użytkownik nie był w stanie zrobić coś takiego:
data = Data()
read("file.csv", data)
data.x = [0, 3, 2, 6, 1]
plot(data)
Zdaję sobie sprawę, że dodanie pojedynczego podkreślenia do nazwy wskazuje użytkownikowi, że atrybut nie powinien zostać zmieniony, tj. Zmień nazwę na _x
i dodaj dekorator właściwości, aby użytkownik mógł uzyskać dostęp do wartości bez poczucia winy. Jednak co zrobić, jeśli chciałam dodać obiekt seter także:
class Data(object):
_x = []
_y = []
@property
def x(self):
return self._x
@x.setter
def x(self, value):
# Do something with value
self._x = value
jestem teraz w takiej samej sytuacji jak ja wcześniej - użytkownik nie może już bezpośrednio uzyskać dostęp do atrybutu _x
, ale nadal można je ustawić go za pomocą:
data.x = [0, 3, 2, 6, 1]
Idealnie byłoby zmienić nazwę definicji funkcji nieruchomość do _x()
, ale prowadzi to do nieporozumień na temat tego, co w rzeczywistości oznacza self._x
(w zależności od kolejności, w jakiej zostały zgłoszone, to wydaje się skutkować albo seter nazywa się rekursywnie, lub ustawiający jest ignorowany na rzecz atrybutu).
Kilka rozwiązań mogę myśleć:
- Dodaj podwójne wiodącego podkreślenia do atrybutu,
__x
, tak że nazwa staje się zniekształcone i nie pomylić z funkcją seter. Jak rozumiem, powinno to być zarezerwowane dla atrybutów, których klasa nie chce udostępniać z możliwymi podklasami, więc nie jestem pewien, czy jest to uzasadnione użycie. - Zmień nazwę atrybutu, np.
_x_stored
. Chociaż rozwiązuje to całkowicie problem, utrudnia odczyt kodu i wprowadza problemy z konwencjami nazewnictwa - które atrybuty zmieniają nazwę? tylko te, które są istotne? tylko te, które mają właściwości? tylko te w tej klasie?
Czy jedno z powyższych rozwiązań ma zastosowanie? A jeśli nie, czy istnieje lepszy sposób na rozwiązanie tego problemu?
Edit
Dzięki za odpowiedzi tak daleko.Kilka punktów rzucone przez komentarze:
- chcę zachować dodatkową logikę, że nieruchomość seter daje mi - rozdział w powyższym przykładzie
# Do something with value
- tak wewnętrznie ustawienie atrybutu poprzez bezpośredni dostępself._x
nie Rozwiąż problem. - Usunięcie właściwości ustawiającego i utworzenie oddzielnej funkcji powoduje, że problem jest rozwiązywany, ale nie jest rozwiązaniem bardzo schludnym, ponieważ umożliwia ustawienie
_x
na dwa różne sposoby - przez wywołanie tej funkcji lub bezpośredni dostęp doself._x
. Musiałbym wtedy śledzić, które atrybuty powinny być ustawione przez ich własną (niezwiązaną z nieruchomością) funkcję ustawiającą i które powinny być modyfikowane przez bezpośredni dostęp. Najprawdopodobniej skorzystam z jednego z rozwiązań, które zasugerowałem powyżej, ponieważ nawet jeśli robią bałagan konwencji nazewnictwa w klasie, to są co najmniej konsekwentne w ich używaniu poza klasą, tj. Wszystkie używają syntaktycznego cukru właściwości . Jeśli nie ma sposobu na zrobienie tego w bardziej uporządkowany sposób, to sądzę, że muszę wybrać ten, który powoduje najmniejsze zakłócenia.
jestem c Zastanawiające się, dlaczego chcesz zdefiniować osobę, która nie chce, aby ludzie używali. – cmd
@cmd - Nadal chcę móc używać settera w innych funkcjach w module. Na przykład, mogę mieć funkcję 'interpolate()', która musi być w stanie ustawić wartości xiy. – sftd
Ale te mogą po prostu ustawić '_x' i' _y'. – kindall