[Tutor] translating some python code to perl

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Thu Aug 28 18:42:10 EDT 2003



On Thu, 28 Aug 2003, Lloyd Kvam wrote:

> This did not generate any responses, but I thought I'd post my solution
> anyway.
>
> #!/usr/bin/perl
> # testhash.pl
>
> %d1 = (
>      '1' => 'one',
>      '2' => 'two',
>      'd2' => {'nest1' => 'nest one',
>      	'nest2' => 'nest two',}
>      );
>
> print "\nlookup 1 in d1: $d1{'1'}\n";
> print "\nlookup d2 within d1: $d1{'d2'}\n";
> print "\nlookup nest1 in d2 within d1: $d1{'d2'}{'nest1'}\n";
> #############
> There's probably a better way, but this seems to work.  The initial
> variable name is prefixed with a % rather than the usual $ and the
> hash is delimited with parentheses.


Hi Lloyd,


Yes.  In Perl, there's a distinction between a "hash" and a "hash
reference".  In Python, there's no such distinction, so technically, that
means that if we're trying to convert something like:


        d1 = {'1' : 'one',
              '2' : 'two',
              'd2': {'nest1': 'nest one',
                     'nest2': 'nest two',
                    },
              '3' : 'four',
              'd3': {'nest3': 'nest three',
                     'nest4': 'nest four'
                    },
             }

then our emitted Perl code should be something like:


       $d1 = {'1'  => 'one',
              '2'  => 'two',
              'd2' => {'nest1' => 'nest one',
                       'nest2' => 'nest two',
                      },
              '3'  => 'four',
              'd3' => {'nest3': 'nest three',
                       'nest4': 'nest four'
                      },
             }



> My python code (version 2.2) follows:
> #!/usr/bin/python
> # py2perl.py
> '''module to handle some python to perl transformations.
> '''
> class Py2perl_dict(dict):
>
> 	def __init__(self, arg):
> 	    super(Py2perl_dict, self).__init__(arg)
> 	    for key,val in self.items():
> 		if isinstance(val, dict) and not isinstance(val, Py2perl_dict):
> 		    self[key] = Py2perl_dict(val)
>
> 	def __repr__(self):
> 	    keylist = self.keys()
> 	    keylist.sort()
> 	    return ''.join(['{',
>                  ','.join(["%s => %s" % (repr(key),repr(self[key])) for key in keylist]),
>                  '}'])



This code works, but also does modifications to our original dictionary.
Seems a harsh price to pay for compatibility.  *grin*



Here's an alternative approach:

###
def renderObject(obj):
    if isinstance(obj, dict):
        return renderDictionary(obj)
    if isinstance(obj, str):
        return renderString(obj)
    raise Exception, ("I don't know how to handle %s" % obj)

def renderDictionary(d):
    rendered_items = []
    for key, value in d.items():
        rendered_items.append("%s => %s" % (renderObject(key),
                                            renderObject(value)))
    return ("{\n%s\n}" % indent(",\n".join(rendered_items)))

def renderString(s):
    return repr(s)

def indent(s):
    indented_lines = ['    ' + l for l in s.split('\n')]
    return '\n'.join(indented_lines)
###



Here's what it looks like when we apply this to our 'd1' dictionary:

###
>>> print renderObject(d1)
{
    '1' => 'one',
    '3' => 'four',
    '2' => 'two',
    'd2' => {
        'nest2' => 'nest two',
        'nest1' => 'nest one'
    },
    'd3' => {
        'nest4' => 'nest four',
        'nest3' => 'nest three'
    }
}
###


Hope this helps!




More information about the Tutor mailing list