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.