Can I prevent an object from being modified in Python?

I want to control global variables (or globally modified variables) so that they are set only once in the program initialization code and block them after that.

I am using UPPER_CASE_VARIABLES for global variables, but I want to have the right way not to change the variable anyway.

  • Does python provide this (or similar) function?
  • How do you control global reach variables?
+12
python global-variables
Sep 14 '10 at 18:08
source share
3 answers

Activestate has a recipe called " Constants in Python" from the venerable Alex Martelli to create a const module with attributes that cannot be restored after creation. It sounds like what you are looking for, except for an increase, but you can add this by checking to see if the attribute name was uppercase or not.

Of course, this can be circumvented by determinants, but the way Python is considered by most people to be a "good thing". However, to make it a little more complicated, I suggest you not worry about adding the supposedly obvious __delattr__ method __delattr__ because then people can just remove the names and then add them back to other values.

This is what I am talking about:

 # Put in const.py... # from http://code.activestate.com/recipes/65207-constants-in-python class _const: class ConstError(TypeError): pass # Base exception class. class ConstCaseError(ConstError): pass def __setattr__(self, name, value): if name in self.__dict__: raise self.ConstError("Can't change const.%s" % name) if not name.isupper(): raise self.ConstCaseError('const name %r is not all uppercase' % name) self.__dict__[name] = value # Replace module entry in sys.modules[__name__] with instance of _const # (and create additional reference to it to prevent its deletion -- see # https://stackoverflow.com/questions/5365562/why-is-the-value-of-name-changing-after-assignment-to-sys-modules-name) import sys _ref, sys.modules[__name__] = sys.modules[__name__], _const() if __name__ == '__main__': import __main__ as const # Test this module... try: const.Answer = 42 # Not OK to create mixed-case attribute name. except const.ConstCaseError as exc: print(exc) else: # Test failed - no ConstCaseError exception generated. raise RuntimeError("Mixed-case const names should't be allowed!") try: const.ANSWER = 42 # Should be OK, all uppercase. except Exception as exc: raise RuntimeError("Changing existing const attribute should't be allowed!") else: # Test succeeded - no exception generated. print('const.ANSWER set to %d raised no exception' % const.ANSWER) try: const.ANSWER = 17 # Not OK, attempt to change defined constant. except const.ConstError as exc: print(exc) else: # Test failed - no ConstError exception generated. raise RuntimeError("Shouldn't be able to change const attribute!") 

Exit:

 const name 'Answer' is not all uppercase const.ANSWER set to 42 raised no exception Can't change const.ANSWER 
+14
Sep 14 '10 at 20:18
source share

Python is a very open language and does not contain the final keyword. Python gives you more freedom to do something and assumes that you know how things should work. Therefore, it is assumed that people using your code will know that SOME_CONSTANT should not be assigned a value at some random point in the code.

If you really want this, you can enclose a constant inside the getter function.

 def getConstant() return "SOME_VALUE" 
+7
Sep 14 '10 at 18:18
source share

You can wrap global variables in an object and override the .__ setattr__ method. You can then prevent the installation of attributes that are already set. However, this does not apply to complex objects that are passed by reference. You will need to make shallow / deep copies of these objects absolutely certain that they cannot be changed. If you use new style classes, you can override the .__ getattribute __ (self, name) object to make copies.

 class State(object): def __init__(self): pass def __setattr__(self, name, value): if name not in self.__dict__: self.__dict__[name] = value 

** Usually I don’t worry so much if someone tries to break my code very badly. I believe that exceeding __setattr__ is sufficient (especially if you make an exception) to warn someone who is playing with code that the goal for the state should be read only. If someone still feels the need for a state change, then any undefined behavior they encounter is not my fault.

+2
Sep 14 '10 at 18:18
source share



All Articles