Home > OS >  python override dot syntax functionality in a class method
python override dot syntax functionality in a class method

Time:09-13

is this possible? I want to assign a value to a custom dictionary using <class_name>.<attribute_name> syntax.

here's an example:

class Foo:
    def __init__(self):
        self.__values__ = {}
    def add_a_value_using_dot_syntax(self, index, value): # what should this be?
        self.__values__[index] = value

bar = Foo()
bar.baz = 'hello'

print(bar.baz) # hello
print(bar.__values__) # {'baz': 'hello'}

I know that this can be done with bracket syntax by overriding __setitem__ but it doesn't seem to work for dot syntax..

Thanks

CodePudding user response:

You can override __getattribute__/__getattr__/__setattr__/__delattr__ to do what you want.

However, you should be very careful when doing so. A lot of code will make assumptions about the attributes of your objects, and it is very easy to break standard data model contracts in a way that makes your class unusable in certain contexts.

CodePudding user response:

Use __setattr__ instead of __setitem__. This method is always called, so you'll want some logic that decides what to do based on the value of the attribute being assigned to.

class Foo:
    def __init__(self):
        self._values = {}  # Do not invent new dunder names

    def __setattr__(self, name, value):
        if name in ["baz", "v1", "v2"]:  # e.g.
            self._values['name'] = value
        else:
            # Assign to name "normally"
            super().__setattr__(name, value)

CodePudding user response:

You'd need to override __getattr__ and __setattr__, but since these are fundamental to how the class works, you'd need some extra logic, and there's an enormous minefield of potentially undefined behavior. I think you'd want

class Foo:
    def __init__(self):
        self.__values__ = {}
        super().__init__()

    def __setattr__(self, name, value):
        if name == '__values__':
            self.__dict__['__values__'] = value
            return
        try:
            self.__getattr__(name)
        except AttributeError:
            self.__values__[name] = value
        return super().__setattr__(name, value)

    def __getattr__(self, name):
        if name == '__values__':
            return self.__dict__['values']
        try:
            return super().__getattr__(name)
        except AttributeError:
            try:
                return self.__values__[name]
            except KeyError:
                raise AttributeError

This is extremely evil/cursed, and should never be done.

  • Related