2016-03-20 11 views
8

Data la seguente classe:Utilità del @property in questo caso

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 

non capisco il motivo per cui utilizzare la funzione di proprietà in questo caso. L'uso del decoratore di proprietà per la funzione input_size consente di chiamare input_size su un oggetto, chiamiamolo cella, di quella classe, ma perché non chiamano semplicemente cell._input_size? Qualcuno può dirmi perché questo è utile per favore?

+1

Chiedi all'autore del codice? Cercare di capire come qualcuno lo usa per renderlo utile è piuttosto ... un compito inutile. –

+1

È nel codice Tensorflow, scritto da google. https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/rnn_cell.py, abbastanza sicuro che siano impegnati a fare qualcosa di più utile di aiutarmi. – eager2learn

risposta

6

L'utilizzo delle proprietà Python presenta vantaggi rispetto all'accesso diretto dei membri suggerito.

valutare l'attuazione

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

vs.

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

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

Supponiamo di avere foo = Foo(). Nel primo caso, si accede al membro come foo.bar. Questo significa che si può fare

print foo.bar 
foo.bar = 3 

cioè non si ha il controllo di limitare le modifiche a bar. In quest'ultimo caso, anche se - basandosi sulla convention not to access things prefixed with _, è vero - si può fare

print foo.bar 

ma

foo.bar = 3 

solleva un'eccezione.

Inoltre, utilizzando property setters, è possibile controllare come bar viene modificato, e fare convalide e altre cose interessanti:

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

(modalità modesto parere: ON)

penso che la sua un abuso di proprietà . Nel corso della giornata, i programmatori C++ e Java hanno capito che l'esposizione dei membri della classe pubblica può rendere fragile il loro codice. Non è possibile cambiare idea su come vengono generati i dati per quella variabile senza modificare l'interfaccia di classe e interrompere la compatibilità con le versioni precedenti. Quindi, le persone hanno iniziato a usare getter e setter (funzioni che accedono ai membri privati) per maggiore flessibilità e c'era una spinta per nascondere tutti i membri ... per ogni evenienza.

Quando altre lingue hanno formalizzato le proprietà, talvolta hanno avuto lo stesso problema con le interfacce di classe. Non è possibile passare da una variabile a una proprietà senza modificare l'interfaccia e, ancora una volta, interrompere la compatibilità con le versioni precedenti. Quindi, c'era una spinta per rendere tutte le proprietà delle variabili ... nel caso.

Python non è così. È possibile avere un membro foo oggi, cambiarlo in una proprietà domani e l'interfaccia di classe non cambia. Ai miei occhi, questa è solo una pratica di codifica difensiva da un'altra lingua e non è necessaria qui.

(modesta opinione: OFF)