Interesuje mnie, jak używać @property
w Pythonie. Przeczytałem dokumentację Pythona, a przykład tam, moim zdaniem, to tylko kod zabawki:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
Nie wiem, jakie korzyści mogę uzyskać dzięki owinięciu _x
wypełnienia dekoratorem nieruchomości. Dlaczego nie wdrożyć jako:
class C(object):
def __init__(self):
self.x = None
Myślę, że funkcja właściwości może być przydatna w niektórych sytuacjach. Ale kiedy? Czy ktoś mógłby mi podać przykłady z prawdziwego świata?
Dzięki.
python
oop
properties
python-decorators
xiao 啸
źródło
źródło
Odpowiedzi:
Inne przykłady to walidacja / filtrowanie ustawionych atrybutów (zmuszanie ich do pozostawania w granicach lub akceptowalnych) oraz leniwa ocena złożonych lub szybko zmieniających się terminów.
Złożone obliczenia ukryte za atrybutem:
Uprawomocnienie:
źródło
Jednym prostym przypadkiem użycia będzie ustawienie atrybutu instancji tylko do odczytu, ponieważ wiesz, że prowadzenie nazwy zmiennej jednym podkreśleniem
_x
w pythonie zwykle oznacza, że jest ona prywatna (do użytku wewnętrznego), ale czasami chcemy mieć możliwość odczytu atrybutu instancji, a nie pisania więc możemy użyćproperty
do tego:źródło
c._x
, jeśli użytkownik chce. Python w rzeczywistości nie ma prawdziwych atrybutów prywatnych.Spójrz na ten artykuł, aby uzyskać bardzo praktyczne zastosowanie. Krótko mówiąc, wyjaśnia, w jaki sposób w Pythonie można zwykle porzucić jawną metodę getter / setter, ponieważ jeśli będziesz ich potrzebować na pewnym etapie, możesz użyć ich
property
do bezproblemowej implementacji.źródło
Jedną z rzeczy, do których go użyłem, jest buforowanie wolno przeszukiwanych, ale niezmiennych wartości przechowywanych w bazie danych. Uogólnia się to na każdą sytuację, w której atrybuty wymagają obliczeń lub innej długiej operacji (np. Sprawdzenie bazy danych, komunikacja sieciowa), którą chcesz wykonywać tylko na żądanie.
Było to w aplikacji internetowej, w której każdy widok strony mógł potrzebować tylko jednego określonego atrybutu tego rodzaju, ale same obiekty bazowe mogą mieć kilka takich atrybutów - inicjowanie ich wszystkich podczas konstrukcji byłoby marnotrawstwem, a właściwości pozwalają mi być elastycznym, w którym atrybuty są leniwe, a które nie.
źródło
@cached_property
?Czytając odpowiedzi i komentarze, wydaje się, że głównym tematem odpowiedzi wydaje się być brak prostego, ale użytecznego przykładu. Dołączyłem tutaj bardzo prosty przykład, który demonstruje proste użycie
@property
dekoratora. Jest to klasa, która pozwala użytkownikowi określić i uzyskać pomiar odległości przy użyciu różnych jednostek, np .in_feet
Lubin_metres
.Stosowanie:
źródło
Właściwość to tylko abstrakcja wokół pola, która zapewnia większą kontrolę nad sposobami manipulowania określonym polem i wykonywania obliczeń oprogramowania pośredniego. Niewiele z przychodzących na myśl zastosowań to sprawdzanie poprawności i wcześniejsza inicjalizacja oraz ograniczenie dostępu
źródło
Tak, w opublikowanym oryginalnym przykładzie właściwość będzie działać dokładnie tak samo, jak po prostu posiadanie zmiennej instancji „x”.
To najlepsza rzecz we właściwościach Pythona. Z zewnątrz działają dokładnie jak zmienne instancji! Co pozwala na użycie zmiennych instancji spoza klasy.
Oznacza to, że Twój pierwszy przykład może faktycznie używać zmiennej instancji. Jeśli coś się zmieniło, a następnie zdecydujesz się zmienić implementację, a właściwość jest przydatna, interfejs tej właściwości będzie nadal taki sam z kodu spoza klasy. Zmiana ze zmiennej instancji na właściwość nie ma wpływu na kod poza klasą.
Wiele innych języków i kursów programowania instruuje programistę, aby nigdy nie ujawniał zmiennych instancji i zamiast tego używał „pobierających” i „ustawiających” dla dowolnej wartości, do której można uzyskać dostęp spoza klasy, nawet w przypadku prostego przypadku, jak podano w pytaniu.
Kod poza klasą z wykorzystaniem wielu języków (np. Java)
Podczas implementacji klasy istnieje wiele funkcji pobierających i ustawiających, które działają dokładnie tak, jak w pierwszym przykładzie: replikują zmienną o prostej instancji. Te metody pobierające i ustawiające są wymagane, ponieważ jeśli implementacja klasy ulegnie zmianie, cały kod poza klasą będzie musiał ulec zmianie. Ale właściwości Pythona pozwalają, aby kod poza klasą był taki sam, jak w przypadku zmiennych instancji. Dlatego kod poza klasą nie musi być zmieniany, jeśli dodajesz właściwość lub masz prostą zmienną instancji. Tak więc w przeciwieństwie do większości języków Object Oriented, dla prostego przykładu ty może użyć instancji zmiennej zamiast „pochłaniacze” i „ustawiaczy”, które nie są naprawdę potrzebne, bezpieczne, wiedząc, że jeśli zmieni się na nieruchomości w przyszłości, kod za pomocą twoja klasa nie musi się zmieniać.
Oznacza to, że potrzebujesz tworzyć właściwości tylko wtedy, gdy występuje złożone zachowanie, a w bardzo powszechnym prostym przypadku, w którym, jak opisano w pytaniu, wystarczy prosta zmienna instancji, możesz po prostu użyć zmiennej instancji.
źródło
kolejna fajna cecha właściwości w stosunku do używania setterów i getters to, że pozwalają ci kontynuować używanie operatorów OP = (np. + =, - =, * = itd.) na twoich atrybutach, jednocześnie zachowując walidację, kontrolę dostępu, buforowanie itp. setery i gettery będą dostarczać.
na przykład, jeśli napisałeś klasę
Person
z seteremsetage(newage)
i gettergetage()
, to aby zwiększyć wiek, musiałbyś napisać:ale jeśli stworzyłeś
age
nieruchomość, możesz napisać znacznie czystsze:źródło
Krótka odpowiedź na twoje pytanie jest taka, że w twoim przykładzie nie ma żadnej korzyści. Powinieneś prawdopodobnie użyć formularza, który nie zawiera właściwości.
Powodem, dla którego istnieją właściwości jest to, że jeśli twój kod zmieni się w przyszłości i nagle będziesz musiał zrobić więcej ze swoimi danymi: wartości pamięci podręcznej, ochrona dostępu, przeszukiwanie zasobów zewnętrznych ... cokolwiek, możesz łatwo zmodyfikować swoją klasę, aby dodać metody pobierające i ustawiających dane bez zmiany interfejsu, więc nie musisz szukać wszędzie w kodzie, gdzie te dane są dostępne, i też tego zmieniać.
źródło
Coś, czego wielu na początku nie zauważa, to fakt, że możesz tworzyć własne podklasy własności. To okazało się bardzo przydatne do ujawniania atrybutów obiektu tylko do odczytu lub atrybutu, który można odczytać i zapisać, ale nie można go usunąć. Jest to również doskonały sposób na zawijanie funkcji, takich jak śledzenie modyfikacji pól obiektów.
źródło
attr = reader('_attr')
linii lub jakiejś formy wstępnego sprawdzania, na przykładattr = if self.__isValid(value): reader('_attr')
. Propozycje?attr = reader('_attr')
naattr = accessor('_attr')
. Dzięki