jason coon
¿Hay algo en Python que funcione como el final
palabra clave en Java, es decir, para no permitir la asignación a un atributo específico de las instancias de una clase, después de que se hayan creado esas instancias? No pude encontrar nada como esto en la documentación.
Estoy creando una instantánea de un objeto (utilizado para la restauración si algo falla); una vez que se asigna esta variable de respaldo, no debe modificarse; final
La función similar en Python sería buena para esto.
Stephan202
No hay final
equivalente en Python. Para crear campos de solo lectura de instancias de clase, puede usar el propiedad función, o podría hacer algo como esto:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
También tenga en cuenta que mientras hay @typing.final
a partir de Python 3.8 (como menciona Cerno), eso no en realidad hacer valores final
en tiempo de ejecución.
-
siempre reemplazo
self.__dict__[attr] = value
conreturn super(WriteORW, self).__setattr__(attr, value)
– John Strod
11 de enero de 2019 a las 8:44
-
Es posible que desee actualizar su respuesta, ya que allí se introdujo en Python 3.8: docs.python.org/3.8/library/…
– Cerno
23 de agosto de 2022 a las 12:50
Tener una variable en Java ser final
básicamente significa que una vez que asigna una variable, no puede reasignar esa variable para que apunte a otro objeto. En realidad, no significa que el objeto no se pueda modificar. Por ejemplo, el siguiente código Java funciona perfectamente bien:
public final List<String> messages = new LinkedList<String>();
public void addMessage()
{
messages.add("Hello World!"); // this mutates the messages list
}
pero lo siguiente ni siquiera compilaría:
public final List<String> messages = new LinkedList<String>();
public void changeMessages()
{
messages = new ArrayList<String>(); // can't change a final variable
}
Entonces tu pregunta es sobre si final
existe en Python. No es asi.
Sin embargo, Python tiene estructuras de datos inmutables. Por ejemplo, si bien puede mutar un list
no puedes mutar un tuple
. Puedes mutar un set
pero no un frozenset
etc.
Mi consejo sería simplemente no preocuparse por hacer cumplir la no mutación a nivel de idioma y simplemente concentrarse en asegurarse de no escribir ningún código que mute estos objetos después de que se asignen.
-
En Java, una variable no primitiva apunta a un objeto. Designar una variable como final significa que no puede hacer que la variable apunte a un objeto diferente, sin embargo, el objeto al que se apunta puede mutar.
– Ardor de Hielo
17 de febrero de 2015 a las 18:49
-
Hay otro uso para final en Java, creo que es lo mismo que static en C++, y es que la línea de código que se asigna a una variable final no se ejecuta más de una vez, incluso si se declara dentro de una función. Le permite ocultar la variable del resto del código sin construir constantemente nuevas instancias cada vez que se llama a las funciones. En Python, debe usar una variable en el ámbito global o aceptar el costo de construir constantemente nuevas instancias. cpp.sh/24gj
–Hatoru Hansou
5 de noviembre de 2015 a las 3:08
-
Me parece una sugerencia horrible para
simply concentrate on making sure that you don't write any code which mutates these objects after they're assigned
. ¿Cómo comunicarás esto a otras personas? ¿O a tu futuro yo? ¿Con un comentario o una cadena de documentación? Una construcción de lenguaje formal es mucho menos volátil que un comentario. Python que carece de esto es, de hecho, preocupante.– delucasvb
7 de enero de 2019 a las 14:13
-
Ya no es preciso para versiones >= 3.8. Vea la respuesta de @congusbongus a continuación.
– Charles Merriam
2 de noviembre de 2019 a las 21:38
-
Después de leer todas las respuestas y bromas del “experto en Python” sobre la declaración de constantes, parece que Python es para un “proyecto de desarrollador único”.
– Tristán
17 de agosto de 2022 a las 16:22
congusbongo
Pitón 3.8 (a través de PEP 591) agrega Final
variables, funciones, métodos y clases. Aquí hay algunas formas de usarlo:
@final
Decorador (clases, métodos)
from typing import final
@final
class Base:
# Cannot inherit from Base
class Base:
@final
def foo(self):
# Cannot override foo in subclass
Final
anotación
from typing import Final
PI: Final[float] = 3.14159 # Cannot set PI to another value
KM_IN_MILES: Final = 0.621371 # Type annotation is optional
class Foo:
def __init__(self):
self.bar: Final = "baz" # Final instance attributes only allowed in __init__
Tenga en cuenta que, al igual que otras sugerencias de escritura, no le impiden anular los tipos, pero ayudan a que los linters o IDE le adviertan sobre el uso incorrecto de tipos.
-
Creo que esta respuesta es engañosa, ya que es fácil tener la impresión de que los calificadores finales evitarán que se reasignen o anulen en el tiempo de ejecución, lo cual no es el caso.
– antonagesta
25 de noviembre de 2019 a las 9:01
-
@antonagestam es una característica del idioma. Los IDE como Visual Studio Code y PyCharm probablemente se adaptarán y mostrarán automáticamente una advertencia si intenta reasignar una instancia final. Este ya es el caso cuando intenta usar una variable de instancia con un prefijo de subrayado fuera de la clase.
– momo
4 de enero de 2020 a las 13:55
-
@momo Al igual que una pregunta sobre propiedades privadas debería tener una respuesta que explique que nada es realmente privado en Python, creo que una respuesta a esta pregunta sugiere usar el
final
/Final
calificadores debe explicar que no hacen nada en tiempo de ejecución. Tenga en cuenta que también respondí esta pregunta.– antonagesta
5 de enero de 2020 a las 20:38
-
Estoy de acuerdo con el comentario de @antonagestam.
@typing.final
solo lo usa el verificador de tipo estático. La respuesta debería dejar más claro que este decorador se ignora por completo al ejecutar el script. Las clases creadas dinámicamente ignorarán silenciosamente este decorador.– Conquilicultor
20 de enero de 2020 a las 20:31
S. Lott
Una variable de asignación única es un problema de diseño. Usted diseña su aplicación de manera que la variable se establezca una vez y solo una vez.
Sin embargo, si desea verificar su diseño en tiempo de ejecución, puede hacerlo con un envoltorio alrededor del 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
Eso es torpe, pero detectará problemas de diseño en tiempo de ejecución.
No existe tal cosa. En general, la actitud de Python es “si no quieres que esto se modifique, simplemente no lo modifiques”. Es poco probable que los clientes de una API solo hurguen en sus partes internas no documentadas de todos modos.
Supongo que podría solucionar esto usando tuplas o tuplas con nombre para las partes relevantes de su modelo, que son intrínsecamente inmutables. Eso todavía no ayuda con ninguna parte de su modelo que tenga que ser mutable, por supuesto.
-
Muchas otras clases también son inmutables: strings, ints, longs, floats.
– S. Lott
29 de abril de 2009 a las 14:37
tíoZeiv
puedes simular algo así a través del protocolo descriptorya que permite definir la lectura y configuración de una variable de la forma que se desee.
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
-
Muchas otras clases también son inmutables: strings, ints, longs, floats.
– S. Lott
29 de abril de 2009 a las 14:37
A partir de 2019 y PEP 591Python tiene un Final
tipo. No estará disponible en la biblioteca estándar hasta el lanzamiento de Python 3.8, pero hasta entonces puede usarlo a través de la extensiones de escritura biblioteca. no funcionará como final
funciona en Java, ya que Python sigue siendo un lenguaje de tipo dinámico. Pero si lo usa junto con un verificador de tipo estático como mipy te dará beneficios muy similares.
También hay una final
decorador que se puede aplicar para marcar métodos de clase como finales y evitar que se anulen. Nuevamente, esto solo se verifica en el “tiempo de compilación”, por lo que deberá incluir un verificador de tipo estático en su flujo de trabajo.
posible duplicado de Creando constante en Python
–Anderson Green
28/02/2014 a las 20:51
@ApurvaSingh Si bien estoy de acuerdo en que Python no es adecuado para eso, hay tuplas y frozenset en la biblioteca estándar y MagicStack/inmutables es una implementación de un mapeo mutable que también se propondrá agregar a la biblioteca estándar.
– antonagesta
14 de septiembre de 2019 a las 8:26