Potrebbe esserci un caso d'uso per le proprietà auto in stile C # in Python

2

Recentemente ho lavorato molto in C # (la mia lingua principale è Python) e mi piace poter fare qualcosa di simile

public string MyProperty{ get; set; }

Tornando a Python mi manca quel tipo di funzionalità. Non mi piace che dovrei fare

class MyClass:

    @property
    def foo(self):
        return self._foo

    @foo.setter
    def foo(self, value):
        self._foo = value

a = MyClass()
a.foo = 7
print(a.foo)

Ho pensato che fosse qualcosa che avrei potuto fare abbastanza facilmente con un descrittore, in questo modo.

class MyClass:
    foo = AutoProperty()

a = MyClass()
a.foo = 7
print(a.foo)

Sfortunatamente, durante l'implementazione mi sono reso conto che stavo violando il mio principio di design preferito: KISS. Dopo tutto, quello a cui stavo pensando erano solo variabili di istanza.

class MyClass(): pass

a = MyClass()
a.foo = 7
print(a.foo)

La ragione per cui in Python non vengono sempre utilizzate le proprietà di default è che, di solito, ottenere e impostare le variabili di istanza non è così complicato come i linguaggi Java, soprattutto perché il concetto di private ,% co_de I campi%, e protected non esistono realmente in Python, tranne per le convenzioni (deboli) e le caratteristiche del linguaggio, e poiché il passaggio da un "campo" a una "proprietà" non è un cambiamento di rottura in Python.

Se in seguito decidiamo che abbiamo bisogno di convalida più complessa durante l'impostazione o i calcoli mentre riceviamo, allora possiamo farlo facilmente implementando le proprietà e non influenzando l'interfaccia della nostra classe.

Mi sto ancora chiedendo - esiste un modo in cui questa tecnica, o una versione modificata di questa tecnica, potrebbe essere usata per fornire una funzione utile?

    
posta Dannnno 26.07.2015 - 19:08
fonte

1 risposta

2

In Python, il passaggio tra un attributo e una proprietà non è una modifica irrisolta, non altera affatto l'interfaccia, quindi non c'è molto da dire su un sistema di proprietà automatica. Puoi iniziare con un attributo pubblico, quindi passare a una proprietà senza dover modificare il codice che si interfaccia con la tua classe.

Questo è anche il motivo per cui la definizione di get_ e set_ metodi in Python è scoraggiata; la proprietà è un modo molto più ordinato di proteggere l'accesso e significa che non è necessario implementare tali metodi dall'inizio, nel caso in cui successivamente si abbia bisogno di fare qualcosa di non banale. Vedi per es. Usi il modello get / set (in Python)? su SO.

Se hai deciso di implementare un AutoProperty dovresti aggiungere anche __delete__ ; Io uso il seguente come base per altri descrittori:

class BaseDescriptor(object):
    """Descriptor base class, providing basic set, get and del methods.

    Arguments:
      name (str): The attribute to redirect access to (usually the name
        to which the descriptor is assigned with a leading underscore,
        indicating private-by-convention).

    Example:

        >>> class TestClass(object):
        ...     foo = BaseDescriptor('_foo')


        >>> inst = TestClass()
        >>> inst.foo = 'bar'
        >>> inst.foo
        'bar'
        >>> del inst.foo
        >>> inst.foo
        Traceback (most recent call last):
          ...
        AttributeError: 'TestClass' object has no attribute '_foo'

    """

    def __init__(self, name):
        self.name = name

    def __get__(self, obj, typ=None):
        return getattr(obj, self.name)

    def __set__(self, obj, val):
        setattr(obj, self.name, val)

    def __delete__(self, obj):
        delattr(obj, self.name)

Updated version for review at https://codereview.stackexchange.com/q/98892/32391

    
risposta data 30.07.2015 - 11:53
fonte

Leggi altre domande sui tag