Si dovrebbe usare un decoratore di proprietà Python senza setter o deleter?

0

Ho una classe che contiene un oggetto (impostato in questo caso). Il set è modificato dagli operatori di funzione standard __add__ e __sub__ , ma voglio anche esporre esplicitamente un metodo per ottenere questo set.

Dovresti usare% decoratore @property invece di un semplice metodo get() , anche se non c'è intenzione di consentire l'impostazione o l'eliminazione?

Ad esempio:

class A(object):

    def __init__(self):
        self.attribute = set() 

    def __add__(self, other):
        self.attribute.add(other)
        return self

    def __sub__(self, other):
        self.attribute.remove(other)
        return self

    @property
    def stuff(self):
        return self.attribute

Sembra semanticamente corretto utilizzare una proprietà e vengono sollevati i giusti messaggi di errore se un tentativo di impostare o eliminare la proprietà si verifica AttributeError: can't set attribute . Ma sembra anche un po 'una truffa per i potenziali utenti che, sapendo che esiste una proprietà, possono aspettarsi che il resto del contratto (impostazione ed eliminazione) sia soddisfatto.

Un'altra opzione potrebbe essere quella di definire il setter / deleter in termini di __add__ e __sub__ ma questa sembra una violazione meno evidente dello stesso contratto.

@stuff.setter
def stuff(self, other):
    self.__add__(other)
    
posta Ben 25.05.2018 - 10:06
fonte

1 risposta

1

Le proprietà di sola lettura sono perfettamente a posto. Sono uno dei pochissimi meccanismi Python per offrire una sorta di incapsulamento.

Non è terribilmente importante se si utilizza una proprietà o un metodo getter, in quanto la differenza è puramente sintattica. Tuttavia, suggeriscono semantica leggermente diversa: una proprietà dovrebbe essere simile a un campo e fornire un accesso diretto a un valore (che può essere calcolato al volo). Un metodo può essere più coinvolto e ha la possibilità di ricevere parametri aggiuntivi.

È preferibile non inserire un comportamento eccessivamente intelligente nelle proprietà, ad esempio aggiungendo al momento dell'assegnazione. Ciò invita solo a problemi difficili di debug, in quanto il contratto di questa proprietà non è ovvio. In effetti, qualsiasi tipo di sovraccarico dell'operatore dovrebbe essere esaminato attentamente. Per esempio. in foo(a + x) dove a = A() , dovresti modificare l'oggetto a ! Questo è abbastanza inaspettato. Potresti voler sovraccaricare __iadd__ , in modo che tu debba utilizzare a += x; foo(a) . Se vuoi un'interfaccia fluente in modo che tu possa modificare il tuo oggetto in un'espressione, allora forse preferisci un nome di metodo con un nome che suggerisce una modifica sul posto, ad es. foo(a.add(x)) .

    
risposta data 25.05.2018 - 10:48
fonte

Leggi altre domande sui tag