Welcome, guest | Sign In | My Account | Store | Cart

The following recipe can be used as a means to adding aliases to methods in a class.

Python, 87 lines
 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.

Created by José Nahuel Cuesta Luengo on Sat, 16 Apr 2011 (MIT)
Python recipes (4591)
José Nahuel Cuesta Luengo's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks