2016-10-04 2 views
0

http://www.programiz.com/python-programming/property Im Anschluss an, ich bin mit dem folgende Verfahren zur Herstellung eine Immobilie in Python Implementierung vertraut:eine Eigenschaft Implementierung des Doppelstern mit (**)

class Celsius(object): 
    def __init__(self, temperature = 0): 
     self._temperature = temperature 

    def get_temperature(self): 
     print("Getting value") 
     return self._temperature 

    def set_temperature(self, value): 
     if value < -273: 
      raise ValueError("Temperature below -273 is not possible") 
     print("Setting value") 
     self._temperature = value 

    temperature = property(get_temperature, set_temperature) 

I, in denen einige Code jetzt bin Lesen des Doppel asterisk (**) wird zum Definieren der Eigenschaft verwendet. Wenn ich es zu meinem eigenen Beispiel anpassen, so scheint es so zu sein:

class Celsius(object): 
    def __init__(self, temperature = 0): 
     self._temperature = temperature 

    def temperature(): 
     def fget(self): 
      print("Getting value") 
      return self._temperature 
     def fset(self, value): 
      if value < -273: 
       raise ValueError("Temperature below -273 is not possible") 
      print("Setting value") 
      self._temperature = value 

    temperature = property(**temperature()) 

Allerdings, wenn ich versuche, diesen Code auszuführen und eine Klasse durch c = Celsius() instanziiert, bekomme ich

TypeError: type object argument after ** must be a mapping, not NoneType 

Ich verstehe dass fget und fset sind Schlüsselwortargumente von property, so würde ich erwarten, was aus **temperature() herauskommt, um etwas wie fget=fget, fset=fset zu sein, aber ich bin nicht sicher, was hier falsch geht oder wie man es weiter seziert. Irgendwelche Ideen?

+3

Nichts kommt aus 'temperature()' heraus. Es gibt keine Rückkehr. Sie definieren 'fget' und' fset' als lokale Funktionen innerhalb 'temperature', aber sie kommen nicht" heraus ", wenn Sie sie nicht zurückgeben. – deceze

Antwort

2

Sie sollten die verschachtelten Funktionen return und sich dann entsprechend dem Funktionsaufruf auspacken:

class Celsius(object): 
    def __init__(self, temperature = 0): 
     self._temperature = temperature 

    def temperature(): 
     ... 
     return fget, fset 

    temperature = property(*temperature()) 

Wenn Sie darauf bestehen ** auf verwenden, dann werden Sie ein Mapping/Wörterbuch aus Ihrer Funktion zurückkehren, die dann sei ausgepackt als Schlüsselwortargumente.

def temperature(): 
    ... 
    return {'fget': fget, 'fset': fset} 

temperature = property(**temperature()) 
+0

Da die Benennung der 'fget'- und' fset'-Funktionen den Schlüsselwortargumenten von 'property' entspricht, kann im zweiten Fall auch 'localies()' anstelle von 'return {' fget ': fget,' fset zurückgegeben werden ': fset} 'wie in meiner' Selbstantwort 'erwähnt. –

1

Sie erhalten diesen Fehler, weil der temperature() Anruf None zurückgibt, die Sie dann versuchen, zu entpacken, als ob es ein Wörterbuch waren, mit **. Um diesen Code zum Laufen zu bringen, müssen Sie ein geeignetes Wörterbuch mit den Setter & Getter-Methoden zurückgeben.

Ich bevorzuge Moses Lösung, aber Sie könnte übergeben Sie die Methoden mit einem dict anstelle eines Tupels, wenn Sie wirklich wollen. ZB

class Celsius(object): 
    def __init__(self, temperature = 0): 
     self._temperature = temperature 

    def temperature(): 
     def fget(self): 
      print("Getting value") 
      return self._temperature 
     def fset(self, value): 
      if value < -273: 
       raise ValueError("Temperature below -273 is not possible") 
      print("Setting value") 
      self._temperature = value 
     return {'fget': fget, 'fset': fset} 

    temperature = property(**temperature()) 

# Test 
a = Celsius() 
a.temperature = 20 
print(a.temperature) 

Ausgang

Setting value 
Getting value 
20 
0

der Tat hatte ich die return Aussage in der Funktionsdefinition von temperature verpasst. Der ursprüngliche Code enthält die Zeile

return locals() 

Das Hinzufügen dieser Zeile bewirkt, dass die Eigenschaft wie gewünscht funktioniert.

+0

Hmm. Ok, das funktioniert, aber ich mag es wirklich nicht, mit 'Locals() 'herumzuspielen, selbst wenn du nur davon liest. –

0

Die temperature-Methode, die Sie definieren, hat keine Rückgabeanweisung, daher gibt sie implizit None zurück, dies ist die ...,not NoneType in Ihrer Fehlermeldung. Das Verfahren zwei Teilverfahren tut, aber das verursacht es nicht, sie in irgendeiner Form zurückzukehren, ich glaube, du eine Zeile wie (ungetestet) fehlen:

return { "fget": fget, "fset": fset } 

Sie auch eine Liste verwenden könnte und ein single *.

Das ist gesagt, es ist eine Best Practice zu vermeiden * und ** Magie, gibt es auch eine pylint rule, um es zu entmutigen.

Verwandte Themen