2012-10-11 24 views

Odpowiedz

12

Powinieneś przeczytać dokumentację na temat rzeczywistych deskryptorów. Wersja Cliff's Notes: descriptors to mechanizm niskiego poziomu, który pozwala na przechwycenie atrybutów obiektu, do których można uzyskać dostęp. Właściwości to aplikacja na wysokim poziomie; to znaczy, właściwości są implementowane za pomocą deskryptorów. Lub jeszcze lepiej, właściwości są deskryptorami, które są już dostępne dla ciebie w standardowej bibliotece.

Jeśli potrzebujesz prostego sposobu na zwrócenie obliczonej wartości z odczytanego atrybutu lub wywołania funkcji przy zapisie atrybutu, użyj dekoratora @property. Deskryptor API jest bardziej elastyczny, ale mniej wygodny i prawdopodobnie "przesadny" i nie-idiomatyczny w tej sytuacji. Jest to przydatne w bardziej zaawansowanych przypadkach użycia, takich jak implementowanie metod związanych lub metod statycznych i klasowych; kiedy musisz wiedzieć, na przykład, czy dostęp do atrybutu był możliwy przez obiekt typu lub instancję typu.

+0

Warto może zauważyć, że pyton zniechęca do korzystania z pobierające i ustawiające wyjątkiem przypadków, gdy to konieczne ... czy to nie może .. –

+3

@JoranBeasley Nie jest to tak odradzane, jak zupełnie niepotrzebne. Ponieważ Python umożliwia zastąpienie dostępu do atrybutów, możesz zdecydować, że potrzebujesz tego w podklasie. Jeśli potrzebujesz wyliczonej właściwości, użyj gettera. W języku Java/C# musisz zdecydować z góry, czy chcesz zezwolić na nadpisanie dostępu do określonego atrybutu i zapewnić to w górnej części hierarchii klas. Dlatego powszechne jest powszechne korzystanie z właściwości: odbywa się "na wszelki wypadek". – millimoose

9

Możesz przeczytać więcej o obu z here. Ale oto prosty przykład z tej samej książki, który próbuje wyjaśnić różnicę, rozwiązując to, co jest zasadniczym problemem. Jak widać, implementacja za pomocą właściwości jest znacznie prostsza.

Istnieje kilka sposobów, w jakie możemy wykorzystać wewnętrzne mechanizmy Pythona do uzyskiwania i ustawiania wartości atrybutów. Najbardziej dostępną techniką jest użycie funkcji property w celu zdefiniowania metod pobierania, ustawiania i usuwania powiązanych z nazwą atrybutu. Funkcja właściwości buduje deskryptory dla ciebie. Technika deskryptorów jest nieco mniej dostępna, ale bardziej rozciągliwa i wielokrotnego użytku. Pozwala to na dużą elastyczność. Robisz to, tworząc klasę, która definiuje metody pobierania, ustawiania i usuwania, a także przypisujesz klasę deskryptorów do nazwy atrybutu.

Funkcja właściwości daje nam wygodny sposób na wdrożenie prostego deskryptora bez definiowania oddzielnej klasy. Zamiast tworzyć pełną definicję klasy, można napisać funkcje metody getter i setter, a następnie powiązać te funkcje z nazwą atrybutu. Przykładem

Eurovoc:

przykład
class Celsius(object): 
    def __init__(self, value=0.0): 
     self.value= float(value) 
    def __get__(self, instance, owner): 
     return self.value 
    def __set__(self, instance, value): 
     self.value= float(value) 

class Farenheit(object): 
    def __get__(self, instance, owner): 
     return instance.celsius * 9/5 + 32 
    def __set__(self, instance, value): 
     instance.celsius= (float(value)-32) * 5/9 

class Temperature(object): 
    celsius= Celsius() 
    farenheit= Farenheit() 
>>> 
oven= Temperature() 
>>> 
oven.farenheit= 450 
>>> 
oven.celsius 
232.22222222222223 
>>> 
oven.celsius= 175 
>>> 
oven.farenheit 
347.0 

nieruchomości:

class Temperature(object): 
    def fget(self): 
     return self.celsius * 9/5 + 32 
    def fset(self, value): 
     self.celsius= (float(value)-32) * 5/9 
    farenheit= property(fget, fset) 
    def cset(self, value): 
     self.cTemp= float(value) 
    def cget(self): 
     return self.cTemp 
    celsius= property(cget, cset, doc="Celsius temperature") 
>>> 
oven= Temperature() 
>>> 
oven.farenheit= 450 
>>> 
oven.celsius 
232.22222222222223 
>>> 
oven.celsius= 175 
>>> 
oven.farenheit 
347.0 
+12

Uważam, że twoje wprowadzenie deskryptora Celsjusza nie jest poprawne.Powinieneś ustawić celsjusz na instancji 'zamiast' self'; Jeśli utworzysz dwa obiekty Temperatury, będą one miały tę samą wartość Celsjusza. –

+0

Uruchomiłem kod "Deskryptor przykład" i działa dobrze. Ale nie rozumiałem, w jaki sposób 'instance.celsius' jest dostępny w klasie' Farenheit'. Dziękuję Ci. – has