How do I create a constant in Python?

后端 未结 30 2617
既然无缘
既然无缘 2020-11-22 09:07

Is there a way to declare a constant in Python? In Java we can create constant values in this manner:

public static          


        
相关标签:
30条回答
  • 2020-11-22 09:31

    You can use StringVar or IntVar, etc, your constant is const_val

    val = 'Stackoverflow'
    const_val = StringVar(val)
    const.trace('w', reverse)
    
    def reverse(*args):
        const_val.set(val)
    
    0 讨论(0)
  • 2020-11-22 09:33

    In my case, I needed immutable bytearrays for an implementation of a crypto library containing many literal numbers I wanted to ensure were constant.

    This answer works but attempted reassignment of bytearray elements does not raise an 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
    

    Constants are immutable, but constant bytearray assignment fails silently:

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

    A more powerful, simple, and perhaps even more 'pythonic' approach involves the use of memoryview objects (buffer objects in <= 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)
    

    ConstArray item assignment is a 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
    
    0 讨论(0)
  • 2020-11-22 09:35

    Python doesn't have constants.

    Perhaps the easiest alternative is to define a function for it:

    def MY_CONSTANT():
        return 42
    

    MY_CONSTANT() now has all the functionality of a constant (plus some annoying braces).

    0 讨论(0)
  • 2020-11-22 09:35

    In addition to the two top answers (just use variables with UPPERCASE names, or use properties to make the values read-only), I want to mention that it's possible to use metaclasses in order to implement named constants. I provide a very simple solution using metaclasses at GitHub which may be helpful if you want the values to be more informative about their type/name:

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

    This is slightly more advanced Python, but still very easy to use and handy. (The module has some more features, including constants being read-only, see its README.)

    There are similar solutions floating around in various repositories, but to the best of my knowledge they either lack one of the fundamental features that I would expect from constants (like being constant, or being of arbitrary type), or they have esoteric features added that make them less generally applicable. But YMMV, I would be grateful for feedback. :-)

    0 讨论(0)
  • 2020-11-22 09:35

    There is a cleaner way to do this with namedtuple:

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

    Usage Example

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

    With this exactly approach you can namespace your constants.

    0 讨论(0)
  • 2020-11-22 09:37

    Python dictionaries are mutable, so they don't seem like a good way to declare constants:

    >>> constants = {"foo":1, "bar":2}
    >>> print constants
    {'foo': 1, 'bar': 2}
    >>> constants["bar"] = 3
    >>> print constants
    {'foo': 1, 'bar': 3}
    
    0 讨论(0)
提交回复
热议问题