The following recipe can be used as a means to adding aliases to methods in a class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | # -*- coding: utf-8 -*-
class alias(object):
"""
Alias class that can be used as a decorator for making methods callable
through other names (or "aliases").
Note: This decorator must be used inside an @aliased -decorated class.
For example, if you want to make the method shout() be also callable as
yell() and scream(), you can use alias like this:
@alias('yell', 'scream')
def shout(message):
# ....
"""
def __init__(self, *aliases):
"""Constructor."""
self.aliases = set(aliases)
def __call__(self, f):
"""
Method call wrapper. As this decorator has arguments, this method will
only be called once as a part of the decoration process, receiving only
one argument: the decorated function ('f'). As a result of this kind of
decorator, this method must return the callable that will wrap the
decorated function.
"""
f._aliases = self.aliases
return f
def aliased(aliased_class):
"""
Decorator function that *must* be used in combination with @alias
decorator. This class will make the magic happen!
@aliased classes will have their aliased method (via @alias) actually
aliased.
This method simply iterates over the member attributes of 'aliased_class'
seeking for those which have an '_aliases' attribute and then defines new
members in the class using those aliases as mere pointer functions to the
original ones.
Usage:
@aliased
class MyClass(object):
@alias('coolMethod', 'myKinkyMethod')
def boring_method():
# ...
i = MyClass()
i.coolMethod() # equivalent to i.myKinkyMethod() and i.boring_method()
"""
original_methods = aliased_class.__dict__.copy()
for name, method in original_methods.iteritems():
if hasattr(method, '_aliases'):
# Add the aliases for 'method', but don't override any
# previously-defined attribute of 'aliased_class'
for alias in method._aliases - set(original_methods):
setattr(aliased_class, alias, method)
return aliased_class
#
# A very simple example
#
@aliased
class Vehicle(object):
def __init__(self, brand, model, color):
"""Constructor."""
self.brand = brand
self.model = model
self.color = color
@alias('modelBrandAndColor', 'getModelBrandAndColour', 'getDescription')
def model_brand_and_color(self):
"""Get the model and brand of this Vehicle."""
return '{0} {1} {2}'.format(self.color, self.brand, self.model)
vehicle = Vehicle('Chevrolet', 'Spark', 'black')
# Now your API looks like your users would want.
# Any of the following lines is equivalent to the others:
print vehicle.model_brand_and_color()
print vehicle.getDescription()
print vehicle.modelBrandAndColor()
print vehicle.getModelBrandAndColour()
|
One useful situation is when your coding standards don't match an API you have to provide and you don't want to sacrifice the beauty of your code. I.E., if you must provide a camelCased API but are using underscored method naming, you can define camelCase aliases for your methods but have them declared as underscored in your code. (See code below for an example).
OR you might be using really ugly naming but want to provide a neat API to your code users. This will help you too.