How do I create a constant in Python?

后端 未结 30 2552
既然无缘
既然无缘 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:26

    Edit: Added sample code for Python 3

    Note: this other answer looks like it provides a much more complete implementation similar to the following (with more features).

    First, make a metaclass:

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

    This prevents statics properties from being changed. Then make another class that uses that metaclass:

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

    Or, if you're using Python 3:

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

    This should prevent instance props from being changed. To use it, inherit:

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

    Now the props, accessed directly or via an instance, should be constant:

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

    Here's an example of above in action. Here's another example for Python 3.

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

    Here is an implementation of a "Constants" class, which creates instances with read-only (constant) attributes. E.g. can use Nums.PI to get a value that has been initialized as 3.14159, and Nums.PI = 22 raises an exception.

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

    Thanks to @MikeGraham 's FrozenDict, which I used as a starting point. Changed, so instead of Nums['ONE'] the usage syntax is Nums.ONE.

    And thanks to @Raufio's answer, for idea to override __ setattr __.

    Or for an implementation with more functionality, see @Hans_meine 's named_constants at GitHub

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

    Maybe pconst library will help you (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.

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

    There's no perfect way to do this. As I understand it most programmers will just capitalize the identifier, so PI = 3.142 can be readily understood to be a constant.

    On the otherhand, if you want something that actually acts like a constant, I'm not sure you'll find it. With anything you do there will always be some way of editing the "constant" so it won't really be a constant. Here's a very simple, dirty example:

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

    This looks like it will make a PHP-style constant.

    In reality all it takes for someone to change the value is this:

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

    This is the same for all the other solutions you'll find on here - even the clever ones that make a class and redefine the set attribute method - there will always be a way around them. That's just how Python is.

    My recommendation is to just avoid all the hassle and just capitalize your identifiers. It wouldn't really be a proper constant but then again nothing would.

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

    (This paragraph was meant to be a comment on those answers here and there, which mentioned namedtuple, but it is getting too long to be fit into a comment, so, here it goes.)

    The namedtuple approach mentioned above is definitely innovative. For the sake of completeness, though, at the end of the NamedTuple section of its official documentation, it reads:

    enumerated constants can be implemented with named tuples, but it is simpler and more efficient to use a simple class declaration:

    class Status:
        open, pending, closed = range(3)
    

    In other words, the official documentation kind of prefers to use a practical way, rather than actually implementing the read-only behavior. I guess it becomes yet another example of Zen of Python:

    Simple is better than complex.

    practicality beats purity.

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

    The Pythonic way of declaring "constants" is basically a module level variable:

    RED = 1
    GREEN = 2
    BLUE = 3
    

    And then write your classes or functions. Since constants are almost always integers, and they are also immutable in Python, you have a very little chance of altering it.

    Unless, of course, if you explicitly set RED = 2.

    0 讨论(0)
提交回复
热议问题