3

I saw this question on SO Prevent creating new attributes outside init which shows how to prevent adding new attributes to objects of classes.

I wanted the same behaviour for the overall class or even the complete loaded module.

Example class:

class Klass:
     a = 0
     b = 1

Another module:

from Klass import Klass

Klass.c = 2 # this should raise an error

Is this possible?

RoQuOTriX
  • 2,871
  • 14
  • 25

2 Answers2

5

If you're trying to prevent modifying the class itself, you can create a metaclass that defines the __setattr__ method for the class.

class FrozenMeta(type):
    def __new__(cls, name, bases, dct):
        inst = super().__new__(cls, name, bases, {"_FrozenMeta__frozen": False, **dct})
        inst.__frozen = True
        return inst
    def __setattr__(self, key, value):
        if self.__frozen and not hasattr(self, key):
            raise TypeError("I am frozen")
        super().__setattr__(key, value)

class A(metaclass=FrozenMeta):
    a = 1
    b = 2

A.a = 2
A.c = 1 # TypeError: I am frozen
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
-1

The answer with slots would be the Pythonic way to do it.

class Klass:
    __slots__ = ['a', 'b']

    def __init__(self, a=0, b=1):
        self.a = a
        self.b = b
>>> k = klass.Klass()
>>> k.a
0
>>> k.b
1
>>> k.c = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Klass' object has no attribute 'c'
>>>