a fairly ugly/kludgy way to get 'aliases' in Python

Bengt Richter bokr at oz.net
Sat Jan 18 02:07:37 CET 2003


On 17 Jan 2003 10:12:45 -0800, Cliff Wells <LogiplexSoftware at earthlink.net> wrote:

>On Thu, 2003-01-16 at 15:52, Jonathan P. wrote:
>class A:
>>   def __init__(self):
>>     self.long_descriptive_name=0
>>     self.long_descriptive_name2=10
>> 
>>   def x(self):
>>     D_=self.__dict__
>>     alias1='long_descriptive_name'
>>     alias2='long_descriptive_name2'
>>     D_[alias]=D_[alias2]*D_[alias1]
          ^^^^^--would have to be alias1 to correspond to next 2 lines
>>     # instead of self.long_descriptive_name =
>>     #  self.long_descriptive_name*self.long_descriptive_name2
       D_[alias1]=D_[alias1]*D_[alias2] # to correspond to above 2 lines
Note that the order in the preceding line is different from your alias version.
It might seem like a nit, but if you are multiplying matrices it's not.

>> 
>> Question: 
>>   Will the dictionary lookup 'D_[alias]' impose a
>>   performance penalty versus 'self.long_descriptive_name' or
>>   will the compiler do the same thing internally anyway in
>>   both cases?
>
>I don't think performance will be affected either way (it's all
>dictionary lookups).  Still, I wonder why you don't just use:
If anything, it might be a shade faster since attribute logic must
do a little work before getting to the __dict__ he's specifying directly.
>
>class A:
>    def __init__(self):
>        self.long_descriptive_name = 0
>        self.long_descriptive_name2 = 10
>
>    def x(self):
>        alias1 = self.long_descriptive_name
>        alias2 = self.long_descriptive_name2
>        self.alias = alias2 * alias1
>
>which would seem to be the equivalent, more readable form.
>
Not quite equivalent. You are binding self.alias with the result,
and he is binding self.<whatever the string value of alias is supposed to be>

(Except I think it was a typo and either his alias1 was supposed to be alias or vice versa).

If you want to do table-driven aliasing in another way, look at the x method below, yet note
that the actual values are stored with the long-name attributes (as seen with vars(a)).
Of course, I'm not sure what all this is about ;-)

===< t_alias.py >==============
class Aliaser(type):
    def __new__(cls, name, bases, cdict):
        for alias, orig in cdict['__rw_aliases__']:
            d = {'alias':alias, 'orig':orig}
            exec ("""\
def _get_%(alias)s(self): return self.%(orig)s
def _set_%(alias)s(self, v): self.%(orig)s = v
%(alias)s = property(_get_%(alias)s, _set_%(alias)s)
""" % d) in cdict
        return type.__new__(cls, name, bases, cdict)

     
class A(object):
    __metaclass__ = Aliaser
    __rw_aliases__ = [
        ('alias1', 'long_descriptive_name'),
        ('alias2', 'long_descriptive_name2')
    ]
    
    def __init__(self):
        self.long_descriptive_name = 1
        self.long_descriptive_name2 = 10
        
    def x(s):
        s.alias1 = s.alias2 * s.alias1

if __name__ == '__main__':
    a = A()
    print A, '=>', a
    for i in range(3):
        print 'alias1=%-4s alias2=%-4s %s' % (a.alias1, a.alias2, vars(a))
        a.x()
===============================

Maybe the long descriptive stuff belongs in doc strings and/or help material
if it's just going to clutter things.

Here's what the output looks like:

[17:12] C:\pywk\meta>t_alias.py
<class '__main__.A'> => <__main__.A object at 0x007DCFE0>
alias1=1    alias2=10   {'long_descriptive_name': 1, 'long_descriptive_name2': 10}
alias1=10   alias2=10   {'long_descriptive_name': 10, 'long_descriptive_name2': 10}
alias1=100  alias2=10   {'long_descriptive_name': 100, 'long_descriptive_name2': 10}

Regards,
Bengt Richter




More information about the Python-list mailing list