You can't override "top level" assignment. But if you can have a root object and work with variables inside a namespace object, then yes, you only have to write the __setattr__
method for that object. It can be a rather simple class, and you can make an instance that is a single letter, so it does not cause negative interference on reading your code - on the contrary, it is easy to perceive that something special is going on:
class NS(object):
def __setattr__(self, name, value):
if name not in self.__dict__:
# Normal, first time assignment:
super(NS, self).__setattr__(name, value)
return
cls = type(self.__dict__[name])
instance = cls(value)
super(NS, self).__setattr__(name, instance)
n = NS()
And on the ineteractive prompt:
In [110]: class MyString(str): pass
...:
...: n.s = MyString()
...:
...: n.s = "bla"
...: type(n.s)
...:
Out[110]: __main__.MyString
Without resorting to a container object, no, there is no way to override assignments - the under-the-hood generated code for that is completely different - as the bytecode sets the variables directly either in the "global" dictionary for the current frame, or in fast-variable caches if the code is running inside a function - meaning that not even the locals
dictionary is touched. That is, it is possible to think of an observer-pattern that takes care of changes in the global dictionary, and takes action when a global variable is changed in a module (if your application is running in a custom event loop, for example) - but that would be too hacky, and would not work for global variables anyway. The namespace object is orders of magnitude simpler.
That said, if you are using Python3, (which you should - and then for one thing - stop worrying about "unicode" or "str" for text) - you could also override the assignment operator in the body of a class: for that you have to create a custom metaclass with a __prepare__
method that would create a mapping object in which the logic you want would be on the __setitem__
method. In this case, Python code just calls the __setitem__
method on this dictionary-like object when it finds an assignment statement.