How can I make an alias to a non-function member attribute in a Python class?
alias, class, python
Solution
You can provide a `__setattr__` and `__getattr__` that reference an aliases map:
class Dummy:
aliases = {
'xValue': 'x',
'another': 'x',
}
def __init__(self):
self.x = 17
def __setattr__(self, name, value):
name = self.aliases.get(name, name)
object.__setattr__(self, name, value)
def __getattr__(self, name):
if name == "aliases":
raise AttributeError # http://nedbatchelder.com/blog/201010/surprising_getattr_recursion.html
name = self.aliases.get(name, name)
return object.__getattribute__(self, name)
d = Dummy()
assert d.x == 17
assert d.xValue == 17
d.x = 23
assert d.xValue == 23
d.xValue = 1492
assert d.x == 1492
Problem
I'm in the midst of writing a Python library API and I often run into the scenario where my users want multiple different names for the same functions and variables. If I have a Python class with the function `foo()` and I want to make an alias to it called `bar()`, that's super easy: ``` class Dummy: def __init__(self): pass def foo(self): pass bar = foo ``` Now I can do this with no problem: ``` d = Dummy() d.foo() d.bar() ``` What I'm wondering is what is the best way to do this with a class attribute that is a regular variable (e.g. a string) rather than a function? If I had this piece of code: ``` d = Dummy() print(d.x) print(d.xValue) ``` I want `d.x` and `d.xValue` to always print the same thing. If `d.x` changes, it should change `d.xValue` also (and vice-versa). I can think of a number of ways to do this, but none of them seem as smooth as I'd like: - Write a custom annotation - Use the `@property` annotation and mess with the setter - Override the `__setattr__` class functions Which of these ways is best? Or is there another way? I can't help but feel that if it's so easy to make aliases for functions, it should be just as easy for arbitrary variables...