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(object):
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...
FYI: I'm using Python 2.7.x, not Python 3.0, so I need a Python 2.7.x compatible solution (though I would be interested if Python 3.0 does something to directly address this need).
Thanks!
Override the
__getattr__()
method and return the appropriate value.You could use some of ideas shown in the ActiveState Python recipe titled Caching and aliasing with descriptors. Here's a concise version of the code shown there which provides the functionality you seek.
Edit: A class containing
Alias
attributes could be made to automatically delete any associated target attributes when youdel
one (and vice-versa). The code for my answer now illustrates one easy way this could be done using a convenient class decorator which adds a custom__delattr__()
to do the specialized deletion management when attributeAlias's
could be involved.Unless I'm misunderstanding the question, this can be solved in almost exactly the same way as with Class methods.
For example,
The two values will always stay in sync. You write the actual property code with the attribute name you prefer, and then you alias it with whatever legacy name(s) you need.
To my eyes, this code is much easier to read and to understand than all of the
__setattr__
and__getattr__
overwriting.What are you going to do when half your users decide to use
d.x
and the other halfd.xValue
? What happens when they try to share code? Sure, it will work, if you know all the aliases, but will it be obvious? Will it be obvious to you when you put away your code for a year?In the end, I think this kind of niceness or luxury is an evil trap that will eventually cause more confusion than good.
You could make aliases with properties this way:
But for the reasons mentioned above, I don't think this is a good design. It makes Dummy harder to read, understand and use. For each user you've doubled the size of the API the user must know in order to understand Dummy.
A better alternative is to use the Adapter design pattern. This allows you to keep Dummy nice, compact, succinct:
While those users in the subdomain who wish to use a different vocabulary can do so by using an Adaptor class:
For each method and attribute in Dummy, you simply hook up similar methods and properties which delegate the heavy lifting to an instance of Dummy.
It might be more lines of code, but it will allow you to preserve a clean design for Dummy, easier to maintain, document, and unit test. People will write code that makes sense because the class will restrict what API is available, and there will be only one name for each concept given the class they've chosen.
You can provide a
__setattr__
and__getattr__
that reference an aliases map: