Question

Je n'ai pas trouvé de documentation sur un équivalent du final de Java en Python. Existe-t-il une telle chose?

Je crée un instantané d'un objet (utilisé pour la restauration en cas d'échec); une fois que cette variable de sauvegarde est affectée, elle ne doit plus être modifiée - une fonctionnalité de type final en Python serait très pratique.

Était-ce utile?

La solution

Le fait qu'une variable en Java soit final signifie en principe qu'une fois que vous avez affecté une variable, vous ne pouvez pas réaffecter cette variable pour qu'elle pointe vers un autre objet. En fait, cela ne signifie pas que l'objet ne peut pas être modifié. Par exemple, le code Java suivant fonctionne parfaitement:

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

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

mais ce qui suit ne compilerait même pas:

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

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

Votre question porte donc sur l'existence de final en Python. Ce n'est pas le cas.

Cependant, Python a des structures de données immuables. Par exemple, bien que vous puissiez modifier une liste , vous ne pouvez pas modifier un tuple . Vous pouvez transformer un set mais pas un frozenset , etc.

Mon conseil serait de ne pas vous soucier de l'application de la non-mutation au niveau de la langue et de vous concentrer simplement sur le fait de ne pas écrire de code qui mue ces objets après leur affectation.

Autres conseils

Il n’existe pas d’équivalent `` final '' en Python.

Toutefois, pour créer des champs d'instances de classe en lecture seule, vous pouvez utiliser le propriété fonction.

Modifier : vous voulez peut-être quelque chose comme ceci:

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

        self.__dict__[attr] = value

Une variable assign-once est un problème de conception. Vous concevez votre application de manière à ce que la variable soit définie une fois et une fois seulement.

Toutefois, si vous souhaitez vérifier votre conception au moment de l'exécution, vous pouvez le faire avec un wrapper autour de l'objet.

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

C'est maladroit, mais cela détectera les problèmes de conception au moment de l'exécution.

Il n'y a rien de tel. En général, l'attitude Python est "si vous ne voulez pas que cela soit modifié, ne le modifiez pas". De toute façon, il est peu probable que les clients d’une API se contentent de fouiller autour de vos composants internes non documentés.

Vous pouvez, je suppose, contourner ce problème en utilisant des tuples ou des tuples nommés pour les bits pertinents de votre modèle, qui sont par nature immuables. Cela n’aide toujours pas les parties de votre modèle qui doivent bien sûr être mutables.

Python n’a pas d’équivalent de "final". Il n'a pas " public " et " protégé " soit, sauf par convention de nommage. Ce n'est pas cela "esclavage et discipline".

vous pouvez simuler quelque chose comme cela via le protocole de descripteur , car il permet de définir la lecture et de définir une variable comme vous le souhaitez.

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/ définit une fonction freeze, bien que cela ne fonctionne pas parfaitement.

Je considérerais simplement de le laisser mutable cependant.

Bien qu'il s'agisse d'une vieille question, j'ai pensé ajouter une autre option potentielle: vous pouvez également utiliser assert pour vérifier qu'une variable est définie sur ce que vous souhaitiez initialement définir sur & # 8211; une double vérification si vous voulez. Bien que ce ne soit pas la même chose que final en Java, il peut être utilisé pour créer un effet similaire:

PI = 3.14
radius = 3

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

Comme indiqué ci-dessus, si PI n'était pour une raison quelconque pas définie sur 3.14 , un AssertionError serait renvoyé, donc un essayez / sauf bloquer serait probablement un ajout judicieux. Quoi qu'il en soit, cela peut s'avérer utile selon votre situation.

Python n’a en effet pas de type final, il a des types immuables tels que les tuples, mais c’est autre chose.

Certaines des autres réponses ici font des classes pleines de pseudo-variables finales et je préfère que ma classe n'ait que quelques types Final, je suggère donc d'utiliser un descripteur pour créer le type final:

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")

Si vous utilisez cette classe comme suit:

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

Ensuite, vous ne pourrez pas définir cette variable dans aucune instance de cette classe. Malheureusement, comme pour la réponse WriteOnceReadWever, vous pouvez toujours définir la variable de classe.

job = SomeJob()
job.FAILED = "Error, this will trigger the ValueError"
SomeJob.FAILED = "However this still works and breaks the protection afterwards"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top