Palavra-chave `final` equivalente para variáveis em Python?
Pergunta
Não consegui encontrar documentação equivalente ao Java final
em Python, existe tal coisa?
Estou criando um instantâneo de um objeto (usado para restauração se algo falhar);uma vez atribuída esta variável de backup, ela não deve ser modificada - um recurso semelhante ao final em Python seria bom para isso.
Solução
Ter uma variável em java ser final
Basicamente, significa que, depois de atribuir a uma variável, você não pode reatribuir essa variável para apontar para outro objeto. Na verdade, não significa que o objeto não pode ser modificado. Por exemplo, o código Java a seguir funciona perfeitamente bem:
public final List<String> messages = new LinkedList<String>();
public void addMessage()
{
messages.add("Hello World!"); // this mutates the messages list
}
Mas o seguinte nem sequer compilaria:
public final List<String> messages = new LinkedList<String>();
public void changeMessages()
{
messages = new ArrayList<String>(); // can't change a final variable
}
Portanto, sua pergunta é sobre se final
Existe em Python. Isso não.
No entanto, o Python possui estruturas de dados imutáveis. Por exemplo, enquanto você pode sofrer muta list
, você não pode sofrer muta tuple
. Você pode mudar um set
mas não um frozenset
, etc.
Meu conselho seria simplesmente não se preocupar em aplicar a não mutação no nível do idioma e simplesmente se concentrar em garantir que você não escreva nenhum código que se afaste desses objetos após o designado.
Outras dicas
Não existe `` final '' equivalente em Python.
Mas, para criar campos somente leitura de instâncias de classe, você pode usar o propriedade função.
Editar: Talvez você queira algo assim:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
Uma variável de atribuição-ONCE é um problema de design. Você cria seu aplicativo de uma maneira que a variável seja definida de uma vez e uma vez.
No entanto, se você deseja verificar o seu design em tempo de execução, poderá fazê-lo com um invólucro ao redor do objeto.
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
Isso é desajeitado, mas detectará problemas de design no tempo de execução.
Não existe tal coisa. Em geral, a atitude do Python é "se você não deseja isso modificado, apenas não o modifique". É improvável que clientes de uma API cutucam seus internos indocumentados.
Suponho que você possa contornar isso usando tuplas ou chamados para os bits relevantes do seu modelo, que são inerentemente imutáveis. Isso ainda não ajuda em nenhuma parte do seu modelo que deve ser mutável, é claro.
Python não tem equivalente a "Final". Também não tem "público" e "protegido", exceto por nomear a Convenção. Não é esse "escravidão e disciplina".
você pode simular algo assim através do Protocolo do descritor, pois permite definir a leitura e a definição de uma variável da maneira que você deseja.
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/ Define uma função de congelamento, embora não funcione perfeitamente.
Eu consideraria apenas deixá -lo mutável.
Embora essa seja uma pergunta antiga, imaginei que acrescentaria mais uma opção potencial: você também pode usar assert
Para verificar uma variável, está definido como o que você pretendia originalmente definir - uma verificação dupla, se você quiser. Embora isso não seja o mesmo que final
Em Java, ele pode ser usado para criar um efeito semelhante:
PI = 3.14
radius = 3
try:
assert PI == 3.14
print PI * radius**2
except AssertionError:
print "Yikes."
Como visto acima, se PI
por algum motivo não foram definidos para 3.14
, um AssertionError
seria jogado, então um try/except
Block provavelmente seria uma adição sábia. Independentemente disso, pode ser útil, dependendo da sua situação.
Na verdade, o Python não possui um tipo final, ele possui tipos imutáveis, como tuplas, mas isso é outra coisa.
Algumas das outras respostas aqui tornam as classes cheias de variáveis pseudofinais e eu prefiro que minha classe tenha apenas alguns tipos Finais, então sugiro usar um descritor para criar o tipo 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")
Se você usar esta classe assim:
class SomeJob:
FAILED = FinalProperty[str]("Failed")
Então você não poderá definir essa variável em nenhuma instância dessa classe.Infelizmente, como acontece com a resposta WriteOnceReadWhenever, você ainda pode definir a variável de classe.
job = SomeJob()
job.FAILED = "Error, this will trigger the ValueError"
SomeJob.FAILED = "However this still works and breaks the protection afterwards"