2016-03-20 13 views
8

die folgende Klasse Gegeben:Usefulness von @property in diesem Fall

class BasicRNNCell(RNNCell): 
    """The most basic RNN cell.""" 

    def __init__(self, num_units, input_size=None): 
    self._num_units = num_units 
    self._input_size = num_units if input_size is None else input_size 

    @property 
    def input_size(self): 
    return self._input_size 

    @property 
    def output_size(self): 
    return self._num_units 

    @property 
    def state_size(self): 
    return self._num_units 

    def __call__(self, inputs, state, scope=None): 
    """Most basic RNN: output = new_state = tanh(W * input + U * state + B).""" 
    with vs.variable_scope(scope or type(self).__name__): # "BasicRNNCell" 
     output = tanh(linear([inputs, state], self._num_units, True)) 
    return output, output 

Ich verstehe nicht, warum sie die Eigenschaft Funktion in diesem Fall verwendet werden. Mit dem Property Decorator für die Funktion input_size kann man input_size für ein Objekt aufrufen, nennen wir es Zelle dieser Klasse, aber warum rufen sie nicht einfach cell._input_size auf? Kann mir jemand sagen, warum das nützlich ist?

+1

Stellen Sie die Urheber des Codes? Zu versuchen, herauszufinden, wie jemand es benutzt, um es nützlich zu machen, ist eher ... vergebliche Aufgabe. –

+1

Es ist in der Tensorflow-Code, von Google geschrieben. https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/rnn_cell.py, ziemlich sicher, dass sie damit beschäftigt sind, etwas Nützlicheres zu tun, als mir zu helfen. – eager2learn

Antwort

6

Die Verwendung von Python-Eigenschaften hat Vorteile gegenüber dem direkten Elementzugriff, den Sie vorschlagen.

Betrachten Sie die Implementierung

class Foo(object): 
    def __init__(self): 
     self.bar = ... 

gegen

class Foo(object): 
    def __init__(self): 
     self._bar = ... 

    ... 
    @property 
    def bar(self): 
     return self._bar 

Angenommen, Sie foo = Foo() haben. Im ersten Fall greifen Sie auf das Mitglied als foo.bar zu. Das bedeutet, dass Sie

print foo.bar 
foo.bar = 3 

D. h tun können, haben Sie keine Kontrolle über Änderungen an bar begrenzen. obwohl im letzteren Fall - auf der convention not to access things prefixed with _ unter Berufung zugegebenermaßen - können Sie

print foo.bar 

tun, aber

foo.bar = 3 

wird eine Ausnahme ausgelöst.

Außerdem mit property setters, können Sie steuern, wie bar geändert wird, und tun Validierungen und andere coole Sachen:

class Foo(object): 
    def __init__(self): 
     self._bar = ... 

    ... 
    @property 
    def bar(self): 
     return self._bar 

    @bar.setter 
    def bar(self, value): 
     if something_of_value(value): 
       raise Whatever 
     self._bar = value 
3

(bescheidene Meinung nach Modus: ON)

Ich denke, die einen Missbrauch von Eigenschaften . Damals erkannten C++ - und Java-Programmierer, dass öffentliche Klassenmitglieder ihren Code fragil machen können. Sie können Ihre Meinung darüber, wie die Daten für diese Variable generiert werden, nicht ändern, ohne die Klassenschnittstelle zu ändern und die Rückwärtskompatibilität zu brechen. Also begannen die Leute mit Getter und Setter (Funktionen, die auf private Mitglieder zugreifen) für zusätzliche Flexibilität und es gab einen Push, um alle Mitglieder zu verstecken ... nur für den Fall.

Wenn andere Sprachen formalisierte Eigenschaften hatten sie manchmal das gleiche Problem mit Klassenschnittstellen. Sie konnten nicht von einer Variablen zu einer Eigenschaft wechseln, ohne die Schnittstelle zu ändern und noch einmal die Rückwärtskompatibilität zu brechen. Also, es gab einen Push, um alle Variablen Eigenschaften zu machen ... nur für den Fall.

Python ist nicht so. Sie können das Mitglied foo heute haben, ändern Sie es morgen in eine Eigenschaft und die Klassenschnittstelle ändert sich nicht. Für mich ist dies nur eine defensive Codierungspraxis aus einer anderen Sprache und wird hier nicht benötigt.

(bescheidene Meinung Modus: OFF)

Verwandte Themen