Domanda

Non sono riuscito a trovare la documentazione su un equivalente del final di Java in Python, esiste una cosa del genere?

Sto creando un'istantanea di un oggetto (utilizzato per il ripristino in caso di errore); una volta che questa variabile di backup è assegnata, non dovrebbe essere modificata - una caratteristica simile a Python sarebbe utile per questo.

È stato utile?

Soluzione

Avere una variabile in Java essere final significa sostanzialmente che una volta assegnata a una variabile, non è possibile riassegnare quella variabile per puntare a un altro oggetto. In realtà non significa che l'oggetto non può essere modificato. Ad esempio, il seguente codice Java funziona perfettamente:

public final List<String> messages = new LinkedList<String>();

public void addMessage()
{
    messages.add("Hello World!");  // this mutates the messages list
}

ma non sarebbe nemmeno possibile compilare quanto segue:

public final List<String> messages = new LinkedList<String>();

public void changeMessages()
{
    messages = new ArrayList<String>();  // can't change a final variable
}

Quindi la tua domanda è se final esiste in Python. Non lo è.

Tuttavia, Python ha strutture di dati immutabili. Ad esempio, mentre puoi mutare un list , non puoi mutare un tuple . Puoi mutare un set ma non un frozenset , ecc.

Il mio consiglio sarebbe di non preoccuparti solo di imporre la non mutazione a livello linguistico e di concentrarmi semplicemente sull'assicurarmi di non scrivere alcun codice che muta questi oggetti dopo che sono stati assegnati.

Altri suggerimenti

Non esiste un equivalente `` finale '' in Python.

Tuttavia, per creare campi di sola lettura delle istanze di classe, puoi utilizzare proprietà .

Modifica : forse vuoi qualcosa del genere:

class WriteOnceReadWhenever:
    def __setattr__(self, attr, value):
        if hasattr(self, attr):
            raise Exception("Attempting to alter read-only value")

        self.__dict__[attr] = value

Una variabile assegnato una volta è un problema di progettazione. Si progetta l'applicazione in modo che la variabile venga impostata una volta e una volta sola.

Tuttavia, se si desidera il controllo del runtime del progetto, è possibile farlo con un wrapper attorno all'oggetto.

class OnePingOnlyPleaseVassily( object ):
    def __init__( self ):
        self.value= None
    def set( self, value ):
        if self.value is not None:
            raise Exception( "Already set.")
        self.value= value

someStateMemo= OnePingOnlyPleaseVassily()
someStateMemo.set( aValue ) # works
someStateMemo.set( aValue ) # fails

È ingombrante, ma rileverà problemi di progettazione in fase di esecuzione.

Non esiste nulla del genere. In generale, l'atteggiamento di Python è " se non vuoi che questo venga modificato, semplicemente non modificarlo " ;. È improbabile che i clienti di un'API si occupino comunque dei tuoi interni privi di documenti.

Potresti, suppongo, aggirare questo problema usando tuple o tuple nominate per i bit rilevanti del tuo modello, che sono intrinsecamente immutabili. Ciò non aiuta ancora con nessuna parte del tuo modello che deve essere naturalmente mutevole.

Python non ha equivalenti di "finale". Non ha " public " e "protetto" o, tranne per convenzione di denominazione. Non è quella "schiavitù e disciplina".

puoi simulare qualcosa del genere attraverso il protocollo descrittore , poiché consente di definire la lettura e l'impostazione di una variabile nel modo desiderato.

class Foo(object):

  @property
  def myvar(self):
     # return value here

  @myvar.setter
  def myvar(self, newvalue):
     # do nothing if some condition is met

a = Foo()
print a.myvar
a.myvar = 5 # does nothing if you don't want to

http://code.activestate.com/recipes/576527/ definisce un funzione di blocco, anche se non funziona perfettamente.

Vorrei prendere in considerazione la possibilità di lasciarlo solo modificabile.

Anche se questa è una vecchia domanda, ho pensato che avrei aggiunto un'altra potenziale opzione: puoi anche usare assert per verificare che una variabile sia impostata su come originariamente intendevi che fosse impostata - a ricontrollando se vuoi. Sebbene questo non sia lo stesso di final in Java, può essere usato per creare un effetto simile:

PI = 3.14
radius = 3

try:
    assert PI == 3.14
    print PI * radius**2
except AssertionError:
    print "Yikes."

Come visto sopra, se PI non fosse per qualche motivo impostato su 3.14 , verrebbe lanciato un AssertionError , quindi un provare / tranne il blocco sarebbe probabilmente un'aggiunta saggia. Indipendentemente da ciò, può tornare utile a seconda della situazione.

Python in effetti non ha un tipo finale, ha tipi immutabili come le tuple ma questo è qualcos'altro.

Alcune delle altre risposte qui rendono le classi piene di pseudo variabili finali e preferisco che la mia classe abbia solo alcuni tipi Final, quindi suggerisco di usare un descrittore per creare il tipo finale:

from typing import TypeVar, Generic, Type

T = TypeVar('T')

class FinalProperty(Generic[T]):
    def __init__(self, value: T):
        self.__value = value
    def __get__(self, instance: Type, owner) -> T:
        return self.__value
    def __set__(self, instance: Type, value: T) -> None:
        raise ValueError("Final types can't be set")

Se usi questa classe in questo modo:

class SomeJob:
    FAILED = FinalProperty[str]("Failed")

Quindi non sarai in grado di impostare quella variabile in nessuna istanza di quella classe. Sfortunatamente, come con la risposta WriteOnceReadWhenever, puoi comunque impostare la variabile di classe.

job = SomeJob()
job.FAILED = "Error, this will trigger the ValueError"
SomeJob.FAILED = "However this still works and breaks the protection afterwards"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top