How can I make an alias to a non-function member attribute in a Python class?

Viewed 10370

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...

6 Answers

This function takes a attribute name as a param and return a property that work as an alias for getting and setting.

def alias_attribute(field_name: str) -> property:
    """
    This function takes the attribute name of field to make a alias and return
    a property that work to get and set.
    """
    field = property(lambda self: getattr(self, field_name))
    field = field.setter(lambda self, value: setattr(self, field_name, value))
    return field

Example:

>>> class A:
...     name_alias = alias_attribute('name')
...     def __init__(self, name):
...         self.name = name
... a = A('Pepe')

>>> a.name
'Pepe'

>>> a.name_alias
'Pepe'

>>> a.name_alias = 'Juan'

>>> a.name
'Juan'
Related