Reputation: 13
In python, I have a class, one of it's attributes is some other class that holds data, like this:
class A:
class Params:
def __init__(self):
self.param1 = None
self.param2 = None
...
def __init__(self):
self.parameters = self.Params()
This way, if anyone wants to change one of the parameters in self.parameters
he can write self.parameters.param1 = ...
.
I want to change the class Params
that holds the parameters into a dictionary
class A:
def __init__(self):
self.parameters = {
'self.param1': None
'self.param2': None
}
This way if anyone wants to change anything he can write self.parameters['param1'] = ...
instead. I've implemented this change (in a development branch) and it works. The problem is that other people use that code and if I make this change it will break their code (it's and simple fix, but still).
I wanted to know if there is any way I can make it so that if anyone writes in the old way (i.e. parameters.param1 = ...
) it would still work but print a DEPRECATED
message when he does, this way I can make a transition window where people go from the old way to the new way. The only way I came up with is if I change the name of the attribute I can keep the old code and add a log.warning
, but I don't want to change the name of the attribute so if anyone can think of a way to do this it would be great :)
Upvotes: 0
Views: 279
Reputation: 531625
You can define make Params
implement the mapping protocol, then produce deprecation warnings on attribute access.
class Params:
def __init__(self):
... # As before
def __setitem__(self, key, value):
# This check is optional, to prevent creating new attributes
if not hasattr(self, key):
raise ValueError(f"No such parameter {key}")
setattr(self, key, value)
__getitem__ = getattr
def __setattr__(self, attr, value):
warnings.warn("Don't set attributes directly", DeprecationWarning)
super().__setattr__(attr, value)
def __getattribute__(self, attr):
warnings.warn("Don't access attributes directly", DeprecationWarning)
super().__getattribute__(self, attr)
Now your next version will support both techniques, but attribute access will raise the warning. In the version after that, you can get rid of the Params
class.
class A:
def __init__(self):
self.parameters = {
'param1': None
'param2': None
}
Upvotes: 1