0

When you create a user-defined class, you can, by default, dinamically add attributes to it just like in the next example:

# User defined class
class Test:
    def __init__(self):
        self.first_att = 5

test = Test()
test.second_att = 11
print(test.__dict__)
{'first_att': 5, 'second_att': 11}

But built-in classes don't allow such a thing:

# Built-in class
str_example = 'Test string'

str_example.added_att = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'added_att'

How can I modify my class Test so it doesn't allow it also? Thanks in advance

3 Answers 3

3

You can achieve that by overwriting the __setattr__ method. As a very simple example for your case

class Test:
    def __init__(self):
        self.first_att = 5

    def __setattr__(self, key, value):
        if key not in ("first_att",):  # allowed attributes
            raise AttributeError(f"Not allowed to set attribute {key}")
        super().__setattr__(key, value)

Note that you have to add an exception list here that holds the names of the attributes you want to be able to assign values to.

Sign up to request clarification or add additional context in comments.

Comments

2

You can define in your class the allowed attributes by adding __slots__.
In there put the names of the attributes you want. All other attributes won't be accepted.
For example try this:

# User defined class
class Test:
    __slots__ = ("fitst_att", "your_att_name")

    def __init__(self):
        self.first_att = 5

test = Test()
test.your_att_name = 11
print(test.__dict__)
# test.second_att = 11  ##this will rais an error

Comments

1

First preventing the user to do a harmless thing is uncommon in Python. Builtin classes do no willingly forbid to add attributes, they simply have static slots instead of a dynamic __dict__ to store their members, because it is simpler to do that when writing a Python class using the C API.

You can mimic that with Python classes by using a __slots__ attribute. But beware, it is not really a security thing, because by default subclasses will receive a __dict__ member and will allow dynamic attributes.

Demo:

class Test:
    __slots__ = ['first_att']
    def __init__(self):
        self.first_att = 5
test = Test()
test.second_att = 7
Traceback (most recent call last):
...
AttributeError: 'Test' object has no attribute 'second_att'

But:

class TestChild(Test):
    pass

child = TestChild()
child.second_att = 7

without any exception...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.