0

I want to set a object in module be readonly and shared in common. Like follow situation:

# configure.py
with open("config.yaml","r") as f:
    config = yaml.load(f)

and configure.py will be used by other scripts. The config object shoud be readonly and fixed.

# data.py
from configure import config
some_operation( config )
# ....
# main.py
from configure import config
config["attr"] = "erroneously_setting"
some_operation( config )

I worry that config object would be erroneously modified by other scripts.

Could I set a variable readonly ?

Siuol Lee
  • 35
  • 4
  • Does this answer your question? [\`final\` keyword equivalent for variables in Python?](https://stackoverflow.com/questions/802578/final-keyword-equivalent-for-variables-in-python) – Alvi15 Dec 16 '22 at 03:56
  • @Alvi15 Note that the `final` decorator is only a type hint for your IDE. It won't stop people from actually modifying the attribute. – Selcuk Dec 16 '22 at 04:01

1 Answers1

2

No, you can't make an attribute read-only in Python, but you can hide the implementation details and use properties to expose attributes:

class Config:
    def __init__(self):
        self._foo = 1

    @property
    def foo(self):
        return self._foo


if __name__ == '__main__':
    config = Config()
    print("Foo is", config.foo)
    config.foo = 1

this will print

Foo is 1

then

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    config.foo = 1
AttributeError: can't set attribute 'foo'

Edit: Here is an example of an immutable dictionary per OP's clarification:

class ImmutableDict(dict):
    def set(self):
        raise NotImplemented()

    def __setitem__(self, *args, **kwargs):
        raise RuntimeError("This is an immutable dictionary")


if __name__ == '__main__':
    my_dict = ImmutableDict({"foo": 1, "bar": 2})
    print(my_dict["foo"])
    my_dict["foo"] = 3

This should print:

1

then

Traceback (most recent call last):
    my_dict["foo"] = 3
    raise RuntimeError("This is an immutable dictionary")
RuntimeError: This is an immutable dictionary
Selcuk
  • 57,004
  • 12
  • 102
  • 110
  • 1
    The problem is that a config object loaded from a YAML file often contains nested containers, which can still be freely mutated even through a class like above. – blhsing Dec 16 '22 at 04:02
  • 5
    @blhsing It is possible to create immutable variants of those data structures if it is strictly necessary, but fair point. – Selcuk Dec 16 '22 at 04:03
  • @Selcuk Thanks, my question should be "how to create immutable dictionary". Simply use property of class should is not demand. – Siuol Lee Dec 17 '22 at 01:29
  • @SiuolLee That's not too hard, you should simply override `__setitem__`. See my updated answer for a trivial example. – Selcuk Dec 17 '22 at 06:22