vacia tipos lista len funciones funcion for español declarar crear como python constants

tipos - ¿Cómo creo una constante en Python?



input python (30)

En Python, las constantes no existen. Pero puede indicar que una variable es una constante y no debe cambiarse agregando ''_CONSTANT'' al comienzo del nombre de la variable, nombrando la variable en BLOCK CAPITALS, y agregando un comentario usando el hashtag (''#''), por ejemplo:

normal_variable = 0 CONSTANT_variable = 1 # This is a constant - do not change its value!

¿Hay alguna manera de declarar una constante en Python? En Java podemos crear valores constantes de esta manera:

public static final String CONST_NAME = "Name";

¿Cuál es el equivalente de la declaración constante de Java anterior en Python?


Además de las dos respuestas principales (solo use variables con nombres en MAYÚSCULAS, o use propiedades para hacer que los valores sean de solo lectura), quiero mencionar que es posible usar metaclases para implementar constantes con nombre . Proporciono una solución muy simple utilizando metaclases en GitHub que puede ser útil si desea que los valores sean más informativos sobre su tipo / nombre:

>>> from named_constants import Constants >>> class Colors(Constants): ... black = 0 ... red = 1 ... white = 15 ... >>> c = Colors.black >>> c == 0 True >>> c Colors.black >>> c.name() ''black'' >>> Colors(0) is c True

Este es un Python ligeramente más avanzado, pero aún así es muy fácil de usar y práctico. (El módulo tiene algunas funciones más, incluidas las constantes que son de solo lectura, consulte README).

Existen soluciones similares que flotan en varios repositorios, pero que yo sepa, o bien carecen de una de las características fundamentales que yo esperaría de las constantes (como ser constante o de tipo arbitrario), o tienen características esotéricas agregadas que Hacerlos menos aplicables en general. Pero YMMV, estaría agradecido por sus comentarios. :-)


Aquí hay una implementación de una clase de "Constantes", que crea instancias con atributos de solo lectura (constante). Por ejemplo, puede usar Nums.PI para obtener un valor que se ha inicializado como 3.14159 , y Nums.PI = 22 genera una excepción.

# ---------- Constants.py ---------- class Constants(object): """ Create objects with read-only (constant) attributes. Example: Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0) print 10 + Nums.PI print ''----- Following line is deliberate ValueError -----'' Nums.PI = 22 """ def __init__(self, *args, **kwargs): self._d = dict(*args, **kwargs) def __iter__(self): return iter(self._d) def __len__(self): return len(self._d) # NOTE: This is only called if self lacks the attribute. # So it does not interfere with get of ''self._d'', etc. def __getattr__(self, name): return self._d[name] # ASSUMES ''_..'' attribute is OK to set. Need this to initialize ''self._d'', etc. #If use as keys, they won''t be constant. def __setattr__(self, name, value): if (name[0] == ''_''): super(Constants, self).__setattr__(name, value) else: raise ValueError("setattr while locked", self) if (__name__ == "__main__"): # Usage example. Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0) print 10 + Nums.PI print ''----- Following line is deliberate ValueError -----'' Nums.PI = 22

Gracias al FrozenDict de @MikeGraham , que usé como punto de partida. Cambiado, así que en lugar de Nums[''ONE''] la sintaxis de uso es Nums.ONE .

Y gracias a la respuesta de @Raufio, por la idea de anular __ setattr __.

O para una implementación con más funcionalidades, vea los nombres_constantes de GitHub


Como probablemente ya sepas, Python no tiene constantes :(

Quizás la alternativa más fácil sea definir una función para ello. P.ej

def MY_CONSTANT(): return 42

MY_CONSTANT() ahora tiene toda la funcionalidad de una constante (más algunas llaves molestas).


Desafortunadamente el Python no tiene constantes todavía y es una vergüenza. ES6 ya ha agregado constantes de soporte a JavaScript ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/const ) ya que es una cosa muy útil en cualquier lenguaje de programación. Como se responde en otras respuestas en la comunidad de Python, use la convención: la variable mayúscula del usuario como constantes, pero no protege contra errores arbitrarios en el código. Si lo desea, puede que le resulte útil una solución de archivo único como la siguiente (vea la documentación sobre cómo usarla).

constantes de archivo.py

import collections __all__ = (''const'', ) class Constant(object): """ Implementation strict constants in Python 3. A constant can be set up, but can not be changed or deleted. Value of constant may any immutable type, as well as list or set. Besides if value of a constant is list or set, it will be converted in an immutable type as next: list -> tuple set -> frozenset Dict as value of a constant has no support. >>> const = Constant() >>> del const.temp Traceback (most recent call last): NameError: name ''temp'' is not defined >>> const.temp = 1 >>> const.temp = 88 Traceback (most recent call last): ... TypeError: Constanst can not be changed >>> del const.temp Traceback (most recent call last): ... TypeError: Constanst can not be deleted >>> const.I = [''a'', 1, 1.2] >>> print(const.I) (''a'', 1, 1.2) >>> const.F = {1.2} >>> print(const.F) frozenset([1.2]) >>> const.D = dict() Traceback (most recent call last): ... TypeError: dict can not be used as constant >>> del const.UNDEFINED Traceback (most recent call last): ... NameError: name ''UNDEFINED'' is not defined >>> const() {''I'': (''a'', 1, 1.2), ''temp'': 1, ''F'': frozenset([1.2])} """ def __setattr__(self, name, value): """Declaration a constant with value. If mutable - it will be converted to immutable, if possible. If the constant already exists, then made prevent againt change it.""" if name in self.__dict__: raise TypeError(''Constanst can not be changed'') if not isinstance(value, collections.Hashable): if isinstance(value, list): value = tuple(value) elif isinstance(value, set): value = frozenset(value) elif isinstance(value, dict): raise TypeError(''dict can not be used as constant'') else: raise ValueError(''Muttable or custom type is not supported'') self.__dict__[name] = value def __delattr__(self, name): """Deny against deleting a declared constant.""" if name in self.__dict__: raise TypeError(''Constanst can not be deleted'') raise NameError("name ''%s'' is not defined" % name) def __call__(self): """Return all constans.""" return self.__dict__ const = Constant() if __name__ == ''__main__'': import doctest doctest.testmod()

Si esto no es suficiente, vea el testcase completo para ello.

import decimal import uuid import datetime import unittest from ..constants import Constant class TestConstant(unittest.TestCase): """ Test for implementation constants in the Python """ def setUp(self): self.const = Constant() def tearDown(self): del self.const def test_create_constant_with_different_variants_of_name(self): self.const.CONSTANT = 1 self.assertEqual(self.const.CONSTANT, 1) self.const.Constant = 2 self.assertEqual(self.const.Constant, 2) self.const.ConStAnT = 3 self.assertEqual(self.const.ConStAnT, 3) self.const.constant = 4 self.assertEqual(self.const.constant, 4) self.const.co_ns_ta_nt = 5 self.assertEqual(self.const.co_ns_ta_nt, 5) self.const.constant1111 = 6 self.assertEqual(self.const.constant1111, 6) def test_create_and_change_integer_constant(self): self.const.INT = 1234 self.assertEqual(self.const.INT, 1234) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.INT = .211 def test_create_and_change_float_constant(self): self.const.FLOAT = .1234 self.assertEqual(self.const.FLOAT, .1234) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.FLOAT = .211 def test_create_and_change_list_constant_but_saved_as_tuple(self): self.const.LIST = [1, .2, None, True, datetime.date.today(), [], {}] self.assertEqual(self.const.LIST, (1, .2, None, True, datetime.date.today(), [], {})) self.assertTrue(isinstance(self.const.LIST, tuple)) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.LIST = .211 def test_create_and_change_none_constant(self): self.const.NONE = None self.assertEqual(self.const.NONE, None) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.NONE = .211 def test_create_and_change_boolean_constant(self): self.const.BOOLEAN = True self.assertEqual(self.const.BOOLEAN, True) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.BOOLEAN = False def test_create_and_change_string_constant(self): self.const.STRING = "Text" self.assertEqual(self.const.STRING, "Text") with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.STRING += ''...'' with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.STRING = ''TEst1'' def test_create_dict_constant(self): with self.assertRaisesRegexp(TypeError, ''dict can not be used as constant''): self.const.DICT = {} def test_create_and_change_tuple_constant(self): self.const.TUPLE = (1, .2, None, True, datetime.date.today(), [], {}) self.assertEqual(self.const.TUPLE, (1, .2, None, True, datetime.date.today(), [], {})) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.TUPLE = ''TEst1'' def test_create_and_change_set_constant(self): self.const.SET = {1, .2, None, True, datetime.date.today()} self.assertEqual(self.const.SET, {1, .2, None, True, datetime.date.today()}) self.assertTrue(isinstance(self.const.SET, frozenset)) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.SET = 3212 def test_create_and_change_frozenset_constant(self): self.const.FROZENSET = frozenset({1, .2, None, True, datetime.date.today()}) self.assertEqual(self.const.FROZENSET, frozenset({1, .2, None, True, datetime.date.today()})) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.FROZENSET = True def test_create_and_change_date_constant(self): self.const.DATE = datetime.date(1111, 11, 11) self.assertEqual(self.const.DATE, datetime.date(1111, 11, 11)) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.DATE = True def test_create_and_change_datetime_constant(self): self.const.DATETIME = datetime.datetime(2000, 10, 10, 10, 10) self.assertEqual(self.const.DATETIME, datetime.datetime(2000, 10, 10, 10, 10)) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.DATETIME = None def test_create_and_change_decimal_constant(self): self.const.DECIMAL = decimal.Decimal(13123.12312312321) self.assertEqual(self.const.DECIMAL, decimal.Decimal(13123.12312312321)) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.DECIMAL = None def test_create_and_change_timedelta_constant(self): self.const.TIMEDELTA = datetime.timedelta(days=45) self.assertEqual(self.const.TIMEDELTA, datetime.timedelta(days=45)) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.TIMEDELTA = 1 def test_create_and_change_uuid_constant(self): value = uuid.uuid4() self.const.UUID = value self.assertEqual(self.const.UUID, value) with self.assertRaisesRegexp(TypeError, ''Constanst can not be changed''): self.const.UUID = [] def test_try_delete_defined_const(self): self.const.VERSION = ''0.0.1'' with self.assertRaisesRegexp(TypeError, ''Constanst can not be deleted''): del self.const.VERSION def test_try_delete_undefined_const(self): with self.assertRaisesRegexp(NameError, "name ''UNDEFINED'' is not defined"): del self.const.UNDEFINED def test_get_all_defined_constants(self): self.assertDictEqual(self.const(), {}) self.const.A = 1 self.assertDictEqual(self.const(), {''A'': 1}) self.const.B = "Text" self.assertDictEqual(self.const(), {''A'': 1, ''B'': "Text"})

Ventajas: 1. Acceso a todas las constantes para todo el proyecto 2. Control estricto para los valores de las constantes

Falta: 1. No es compatible con los tipos personalizados y el tipo ''dict''

Notas:

  1. Probado con Python3.4 y Python3.5 (estoy usando el ''tox'' para ello)

  2. Entorno de prueba:

.

$ uname -a Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux


Edición: Código de ejemplo agregado para Python 3

Nota: esta otra respuesta parece que proporciona una implementación mucho más completa similar a la siguiente (con más características).

Primero, haz una metaclass :

class MetaConst(type): def __getattr__(cls, key): return cls[key] def __setattr__(cls, key, value): raise TypeError

Esto evita que se modifiquen las propiedades estáticas. Luego haz otra clase que use esa metaclase:

class Const(object): __metaclass__ = MetaConst def __getattr__(self, name): return self[name] def __setattr__(self, name, value): raise TypeError

O, si estás usando Python 3:

class Const(object, metaclass=MetaConst): def __getattr__(self, name): return self[name] def __setattr__(self, name, value): raise TypeError

Esto debería evitar que se cambien los accesorios de instancia. Para usarlo, hereda:

class MyConst(Const): A = 1 B = 2

Ahora los accesorios, accedidos directamente oa través de una instancia, deben ser constantes:

MyConst.A # 1 my_const = MyConst() my_const.A # 1 MyConst.A = ''changed'' # TypeError my_const.A = ''changed'' # TypeError

Here''s un ejemplo de lo anterior en acción. Here''s otro ejemplo para Python 3.


En Python, en lugar de que el lenguaje aplique algo, las personas usan convenciones de nomenclatura, por ejemplo, __method para métodos privados y el uso de _method para métodos protegidos.

De la misma manera, simplemente puede declarar la constante como mayúsculas, por ejemplo,

MY_CONSTANT = "one"

Si desea que esta constante nunca cambie, puede enlazar con el acceso de atributos y hacer trucos, pero un enfoque más simple es declarar una función

def MY_CONSTANT(): return "one"

El único problema está en todas partes, tendrá que hacer MY_CONSTANT (), pero nuevamente MY_CONSTANT = "one" es la forma correcta en python (generalmente).

También puedes usar namedtuple para crear constantes:

>>> from collections import namedtuple >>> Constants = namedtuple(''Constants'', [''pi'', ''e'']) >>> constants = Constants(3.14, 2.718) >>> constants.pi 3.14 >>> constants.pi = 3 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can''t set attribute


En Python, una constante es simplemente una variable con un nombre en mayúsculas, con palabras separadas por el carácter de subrayado,

p.ej

DAYS_IN_WEEK = 7

El valor es mutable, ya que en él puedes cambiarlo. Pero dadas las reglas para que el nombre te diga es una constante, ¿por qué lo harías? Quiero decir, es tu programa después de todo!

Este es el enfoque adoptado a lo largo de python. No hay private palabra clave private por la misma razón. Prefije el nombre con un guión bajo y sabrá que está destinado a ser privado. El código puede romper la regla ... así como un programador podría eliminar la palabra clave privada de todos modos.

Python podría haber agregado una palabra clave const ... pero un programador podría eliminar una palabra clave y luego cambiar la constante si lo desean, pero ¿por qué hacer eso? Si desea romper la regla, podría cambiar la regla de todos modos. ¿Pero por qué molestarse en romper la regla si el nombre aclara la intención?

¿Tal vez hay alguna prueba de unidad donde tiene sentido aplicar un cambio al valor? Para ver qué sucede en una semana de 8 días, aunque en el mundo real no se puede cambiar la cantidad de días de la semana. Si el lenguaje le impidió hacer una excepción, solo en este caso debe romper la regla ... deberá dejar de declararlo como una constante, a pesar de que aún es una constante en la aplicación, y hay solo este caso de prueba que ve lo que sucede si se cambia.

El nombre en mayúsculas le indica que se pretende que sea una constante. Eso es lo importante. No es un idioma el que impone restricciones en el código, de todos modos tiene el poder de cambiar.

Esa es la filosofía de python.


En mi caso, necesitaba inmutables bytearrays para una implementación de una biblioteca criptográfica que contenía muchos números literales que quería asegurar que fueran constantes.

Esta respuesta funciona, pero el intento de reasignación de elementos bytearray no genera un error.

def const(func): ''''''implement const decorator'''''' def fset(self, val): ''''''attempting to set a const raises `ConstError`'''''' class ConstError(TypeError): ''''''special exception for const reassignment'''''' pass raise ConstError def fget(self): ''''''get a const'''''' return func() return property(fget, fset) class Consts(object): ''''''contain all constants'''''' @const def C1(): ''''''reassignment to C1 fails silently'''''' return bytearray.fromhex(''deadbeef'') @const def pi(): ''''''is immutable'''''' return 3.141592653589793

Las constantes son inmutables, pero la asignación constante del bytearray falla silenciosamente:

>>> c = Consts() >>> c.pi = 6.283185307179586 # (https://en.wikipedia.org/wiki/Tau_(2%CF%80)) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "consts.py", line 9, in fset raise ConstError __main__.ConstError >>> c.C1[0] = 0 >>> c.C1[0] 222 >>> c.C1 bytearray(b''/xde/xad/xbe/xef'')

Un enfoque más poderoso, simple y tal vez incluso más "pitónico" implica el uso de objetos de vista de memoria (objetos de búfer en <= python-2.6).

import sys PY_VER = sys.version.split()[0].split(''.'') if int(PY_VER[0]) == 2: if int(PY_VER[1]) < 6: raise NotImplementedError elif int(PY_VER[1]) == 6: memoryview = buffer class ConstArray(object): ''''''represent a constant bytearray'''''' def __init__(self, init): '''''' create a hidden bytearray and expose a memoryview of that bytearray for read-only use '''''' if int(PY_VER[1]) == 6: self.__array = bytearray(init.decode(''hex'')) else: self.__array = bytearray.fromhex(init) self.array = memoryview(self.__array) def __str__(self): return str(self.__array) def __getitem__(self, *args, **kwargs): return self.array.__getitem__(*args, **kwargs)

La asignación de elementos de ConstArray es un TypeError:

>>> C1 = ConstArray(''deadbeef'') >>> C1[0] = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: ''ConstArray'' object does not support item assignment >>> C1[0] 222


Haría una clase que reemplaza el método __setattr__ de la clase de objeto base y envolvería mis constantes con eso, tenga en cuenta que estoy usando Python 2.7:

class const(object): def __init__(self, val): super(const, self).__setattr__("value", val) def __setattr__(self, name, val): raise ValueError("Trying to change a constant value", self)

Para envolver una cadena:

>>> constObj = const("Try to change me") >>> constObj.value ''Try to change me'' >>> constObj.value = "Changed" Traceback (most recent call last): ... ValueError: Trying to change a constant value >>> constObj2 = const(" or not") >>> mutableObj = constObj.value + constObj2.value >>> mutableObj #just a string ''Try to change me or not''

Es bastante simple, pero si desea usar sus constantes de la misma manera que lo haría con un objeto no constante (sin usar constObj.value), será un poco más intensivo. Es posible que esto pueda causar problemas, por lo que sería mejor mantener el valor .value para mostrar y saber que está haciendo operaciones con constantes (aunque tal vez no sea la forma más "pitónica").


La forma Pythonic de declarar "constantes" es básicamente una variable de nivel de módulo:

RED = 1 GREEN = 2 BLUE = 3

Y luego escribe tus clases o funciones. Dado que las constantes son casi siempre enteros, y también son inmutables en Python, tienes muy pocas posibilidades de alterarlo.

A menos, por supuesto, si establece explícitamente RED = 2 .


Las propiedades son una forma de crear constantes. Puede hacerlo declarando una propiedad getter, pero ignorando el setter. Por ejemplo:

class MyFinalProperty(object): @property def name(self): return "John"

Puede echar un vistazo a un artículo que he escrito para encontrar más formas de usar las propiedades de Python.


Los diccionarios de Python son mutables, por lo que no parecen ser una buena manera de declarar constantes:

>>> constants = {"foo":1, "bar":2} >>> print constants {''foo'': 1, ''bar'': 2} >>> constants["bar"] = 3 >>> print constants {''foo'': 1, ''bar'': 3}


No hay una palabra clave const como en otros idiomas, sin embargo, es posible crear una Propiedad que tenga una "función de obtención" para leer los datos, pero no una "función de configuración" para volver a escribir los datos. Esto esencialmente protege el identificador de ser cambiado.

Aquí hay una implementación alternativa usando la propiedad de clase:

Tenga en cuenta que el código no es fácil para un lector que se pregunta sobre constantes. Ver explicación abajo

def constant(f): def fset(self, value): raise TypeError def fget(self): return f() return property(fget, fset) class _Const(object): @constant def FOO(): return 0xBAADFACE @constant def BAR(): return 0xDEADBEEF CONST = _Const() print CONST.FOO ##3131964110 CONST.FOO = 0 ##Traceback (most recent call last): ## ... ## CONST.FOO = 0 ##TypeError: None

Explicación del código:

  1. Defina una constant función que toma una expresión y la usa para construir un "captador", una función que únicamente devuelve el valor de la expresión.
  2. La función de establecimiento genera un TypeError por lo que es de solo lectura
  3. Utilice la función constant que acabamos de crear como decoración para definir rápidamente las propiedades de solo lectura.

Y de alguna otra manera más antigua:

(El código es bastante complicado, más explicaciones a continuación)

class _Const(object): @apply def FOO(): def fset(self, value): raise TypeError def fget(self): return 0xBAADFACE return property(**locals()) CONST = _Const() print CONST.FOO ##3131964110 CONST.FOO = 0 ##Traceback (most recent call last): ## ... ## CONST.FOO = 0 ##TypeError: None

Tenga en cuenta que el decorador @apply parece estar en desuso.

  1. Para definir el identificador FOO, firs define dos funciones (fset, fget - los nombres están a mi elección).
  2. Luego use la función de property incorporada para construir un objeto que se pueda "establecer" o "obtener".
  3. Tenga en cuenta que los dos primeros parámetros de la función de property se denominan fset y fget .
  4. Utilice el hecho de que elegimos estos mismos nombres para nuestro propio getter & setter y creamos un diccionario de palabras clave utilizando el ** (doble asterisco) aplicado a todas las definiciones locales de ese alcance para pasar parámetros a la función de property

No no hay. No puede declarar una variable o un valor como constante en Python. Simplemente no lo cambies.

Si estás en una clase, el equivalente sería:

class Foo(object): CONST_NAME = "Name"

si no, es solo

CONST_NAME = "Name"

Pero es posible que desee ver el fragmento de código Constantes en Python por Alex Martelli.


Probablemente me esté faltando un truco aquí, pero esto parece funcionar para mí:

class CONST(object): FOO = 1234 def __setattr__(self, *_): pass CONST = CONST() #---------- print CONST.FOO # 1234 CONST.FOO = 4321 CONST.BAR = 5678 print CONST.FOO # Still 1234! print CONST.BAR # Oops AttributeError

Crear la instancia permite que el método magic __setattr__ e intercepte los intentos de establecer la variable FOO . Podrías lanzar una excepción aquí si quisieras. La creación de instancias de la instancia sobre el nombre de la clase impide el acceso directamente a través de la clase.

Es un dolor total para un valor, pero podría adjuntar lotes a su objeto CONST . Teniendo una clase alta, el nombre de la clase también parece un poco malhumorado, pero creo que es bastante breve en general.


Puede usar un grupo con nombre como solución alternativa para crear efectivamente una constante que funcione de la misma manera que una variable final estática en Java (una "constante" de Java). Como soluciones, es algo elegante. (Un enfoque más elegante sería simplemente mejorar el lenguaje Python --- ¿qué tipo de lenguaje te permite redefinir math.pi ? - pero estoy divagando).

(A medida que escribo esto, me doy cuenta de que otra respuesta a esta pregunta mencionada se nombra tu doble, pero continuaré aquí porque mostraré una sintaxis que se asemeja más a lo que esperarías en Java, ya que no hay necesidad de crear un nombre escribe como namedtuple te obliga a hacerlo.)

Siguiendo su ejemplo, recordará que en Java debemos definir la constante dentro de alguna clase ; porque no mencionaste un nombre de clase, llamémoslo Foo . Aquí está la clase de Java:

public class Foo { public static final String CONST_NAME = "Name"; }

Aquí está el equivalente de Python.

from collections import namedtuple Foo = namedtuple(''_Foo'', ''CONST_NAME'')(''Name'')

El punto clave que quiero agregar aquí es que no necesita un tipo de Foo separado (una "tupla llamada anónima" sería agradable, aunque eso suene como un oxímoron), por lo que llamamos a nuestra tupla _Foo para que, con suerte, _Foo ganando No escape a la importación de módulos.

El segundo punto aquí es que inmediatamente creamos una instancia del nombre, llamándola Foo ; no hay necesidad de hacer esto en un paso separado (a menos que desee). Ahora puedes hacer lo que puedes hacer en Java:

>>> Foo.CONST_NAME ''Name''

Pero no puedes asignárselo:

>>> Foo.CONST_NAME = ''bar'' … AttributeError: can''t set attribute

Reconocimiento: pensé que había inventado el enfoque de doble grupo, pero luego veo que alguien más dio una respuesta similar (aunque menos compacta). Entonces también noté ¿Qué son las "tuplas nombradas" en Python? , lo que señala que sys.version_info ahora es un tupla nombrado, por lo que quizás la biblioteca estándar de Python ya tuvo esta idea mucho antes.

Tenga en cuenta que desafortunadamente (aún siendo Python), puede borrar toda la asignación de Foo completo:

>>> Foo = ''bar''

(facepalm)

Pero al menos estamos evitando que se Foo.CONST_NAME valor de Foo.CONST_NAME , y eso es mejor que nada. Buena suerte.


Simplemente puedes simplemente

STRING_CONSTANT = "hi" NUMBER_CONSTANT = 89

Espero que todo sea mucho más sencillo.


Una tupla técnicamente califica como una constante, ya que una tupla generará un error si intenta cambiar uno de sus valores. Si desea declarar una tupla con un valor, coloque una coma después de su único valor, como este:

my_tuple = (0 """Or any other value""",)

Para verificar el valor de esta variable, usa algo similar a esto:

if my_tuple[0] == 0: #Code goes here

Si intenta cambiar este valor, se generará un error.


Aquí hay un truco si quieres constantes y no te importan sus valores:

Solo define clases vacias.

p.ej:

class RED: pass class BLUE: pass


Hay una forma más limpia de hacer esto con namedtuple:

from collections import namedtuple def make_consts(name, **kwargs): return namedtuple(name, kwargs.keys())(**kwargs)

Ejemplo de uso

CONSTS = make_consts("baz1", foo=1, bar=2)

Con este enfoque exacto puedes poner espacios de nombres a tus constantes.


Podemos crear un objeto descriptor:

class Constant: def __init__(self,value=None): self.value = value def __get__(self,instance,owner): return self.value def __set__(self,instance,value): raise ValueError("You can''t change a constant") class A: NULL = Constant() NUM = Constant(0xFF) class B: NAME = Constant(''bar'') LISTA = Constant([0,1,''INFINITY'']) >>> obj=A() >>> print(obj.NUM) #=> 255 >>> obj.NUM =100 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: You can''t change a constant


Puede ajustar una constante en una matriz numpy, marcarla solo para escribir y llamarla siempre por el índice cero.

import numpy as np # declare a constant CONSTANT = ''hello'' # put constant in numpy and make read only CONSTANT = np.array([CONSTANT]) CONSTANT.flags.writeable = False # alternatively: CONSTANT.setflags(write=0) # call our constant using 0 index print ''CONSTANT %s'' % CONSTANT[0] # attempt to modify our constant with try/except new_value = ''goodbye'' try: CONSTANT[0] = new_value except: print "cannot change CONSTANT to ''%s'' it''s value ''%s'' is immutable" % ( new_value, CONSTANT[0]) # attempt to modify our constant producing ValueError CONSTANT[0] = new_value >>> CONSTANT hello cannot change CONSTANT to ''goodbye'' it''s value ''hello'' is immutable Traceback (most recent call last): File "shuffle_test.py", line 15, in <module> CONSTANT[0] = new_value ValueError: assignment destination is read-only

por supuesto, esto solo protege el contenido del número, no la propia variable "CONSTANTE"; todavía puedes hacer

CONSTANT = ''foo''

y CONSTANTcambiaría, sin embargo, eso lanzaría rápidamente un TypeError la primera vez que CONSTANT[0]se llamara en el script.

aunque ... supongo que si en algún momento lo cambiaste a

CONSTANT = [1,2,3]

ahora ya no obtendrías el TypeError. hmmmm ....

https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html


bueno ... aunque esto no esté actualizado, déjame agregar mis 2 centavos aquí :-)

class ConstDict(dict): def __init__(self, *args, **kwargs): super(ConstDict, self).__init__(*args, **kwargs) def __setitem__(self, key, value): if key in self: raise ValueError("Value %s already exists" % (key)) super(ConstDict, self).__setitem__(key, value)

En lugar de que ValueError se rompa, puede evitar que se realicen actualizaciones allí. Una ventaja de esto es que puede agregar constantes dinámicamente en el programa pero no puede cambiar una vez que se establece una constante. También puede agregar cualquier regla o lo que sea antes de establecer una constante (algo así como una clave debe ser una cadena o una cadena en minúscula o una cadena en mayúsculas y así sucesivamente antes de configurar la tecla)

Sin embargo, no veo ninguna importancia de establecer constantes en Python. Ninguna optimización puede ocurrir como en C y, por lo tanto, es algo que no es necesario, supongo.


Escribo una libreria util para python const: kkconst - pypi support str, int, float, datetime

La instancia del campo const mantendrá su comportamiento de tipo base.

Por ejemplo:

from __future__ import print_function from kkconst import ( BaseConst, ConstFloatField, ) class MathConst(BaseConst): PI = ConstFloatField(3.1415926, verbose_name=u"Pi") E = ConstFloatField(2.7182818284, verbose_name=u"mathematical constant") # Euler''s number" GOLDEN_RATIO = ConstFloatField(0.6180339887, verbose_name=u"Golden Ratio") magic_num = MathConst.GOLDEN_RATIO assert isinstance(magic_num, ConstFloatField) assert isinstance(magic_num, float) print(magic_num) # 0.6180339887 print(magic_num.verbose_name) # Golden Ratio

Para más detalles, puedes leer la URL de pypi : pypi o github


Extendiendo la respuesta de Raufio, agregue una repetición para devolver el valor.

class const(object): def __init__(self, val): super(const, self).__setattr__("value", val) def __setattr__(self, name, val): raise ValueError("Trying to change a constant value", self) def __repr__(self): return (''{0}''.format(self.value)) dt = const(float(0.01)) print dt

entonces el objeto se comporta un poco más como usted podría esperar, puede acceder a él directamente en lugar de ''.valor''


No hay una manera perfecta de hacer esto. Según tengo entendido, la mayoría de los programadores simplemente usarán mayúsculas en el identificador, por lo que PI = 3.142 puede entenderse fácilmente como una constante.

Por otro lado, si quieres algo que realmente actúa como una constante, no estoy seguro de que lo encuentres. Con cualquier cosa que hagas, siempre habrá alguna forma de editar la "constante", por lo que realmente no será una constante. Aquí hay un ejemplo muy simple y sucio:

def define(name, value): if (name + str(id(name))) not in globals(): globals()[name + str(id(name))] = value def constant(name): return globals()[name + str(id(name))] define("PI",3.142) print(constant("PI"))

Esto parece que hará una constante de estilo PHP.

En realidad, todo lo que se necesita para que alguien cambie el valor es esto:

globals()["PI"+str(id("PI"))] = 3.1415

Esto es lo mismo para todas las otras soluciones que encontrará aquí, incluso las inteligentes que forman una clase y redefinen el método de atributos establecidos, siempre habrá una forma de evitarlos. Así es como es Python.

Mi recomendación es simplemente evitar toda la molestia y simplemente poner en mayúscula sus identificadores. Realmente no sería una constante adecuada pero, de nuevo, nada sería.


Puede emular variables constantes con la ayuda de la siguiente clase. Un ejemplo de uso:

# Const const = Const().add(two=2, three=3) print ''const.two: '', const.two print ''const.three: '', const.three const.add(four=4) print ''const.four: '', const.four #const.four = 5 # a error here: four is a constant const.add(six=6) print ''const.six: '', const.six const2 = Const().add(five=5) # creating a new namespace with Const() print ''const2.five: '', const2.five #print ''const2.four: '', const2.four # a error here: four does not exist in const2 namespace const2.add(five=26)

Llame al constructor cuando desee iniciar un nuevo espacio de nombres constante. Tenga en cuenta que la clase está protegida contra las constantes de tipo de secuencia de modificación inesperadas cuando la clase const de Martelli no lo está.

La fuente está abajo.

from copy import copy class Const(object): "A class to create objects with constant fields." def __init__(self): object.__setattr__(self, ''_names'', []) def add(self, **nameVals): for name, val in nameVals.iteritems(): if hasattr(self, name): raise ConstError(''A field with a name /'%s/' is already exist in Const class.'' % name) setattr(self, name, copy(val)) # set up getter self._names.append(name) return self def __setattr__(self, name, val): if name in self._names: raise ConstError(''You cannot change a value of a stored constant.'') object.__setattr__(self, name, val)


Puede usar StringVar o IntVar, etc., su constante es const_val

val = '''' const_val = StringVar(val) const.trace(''w'', reverse) def reverse(*args): const_val.set(val)


Tal vez la biblioteca pconst te ayude ( github ).

$ pip install pconst

from pconst import const const.APPLE_PRICE = 100 const.APPLE_PRICE = 200

[Out] Constant value of "APPLE_PRICE" is not editable.