Lexical scope: converting Perl to Python

John S jstrickler at gmail.com
Sat Jun 13 16:11:46 EDT 2009


On Jun 13, 8:29 am, Nick Craig-Wood <n... at craig-wood.com> wrote:
> Andrew Savige <ajsav... at yahoo.com.au> wrote:
>
> >  I'd like to convert the following Perl code to Python:
>
> >   use strict;
> >   {
> >     my %private_hash = ( A=>42, B=>69 );
> >     sub public_fn {
> >       my $param = shift;
> >       return $private_hash{$param};
> >     }
> >   }
> >   print public_fn("A");        # good:  prints 42
> >   my $x = $private_hash{"A"};  # error: good, hash not in scope
>
> >  The real code is more complex; the above is a simplified example.
>
> >  Notice that this code uses Perl's lexical scope to hide the
> >  %private_hash variable, but not the public_fn() function.
>
> >  While I could convert this code to the following Python code:
>
> >   private_hash = dict( A=42, B=69 )
> >   def public_fn(param):
> >     return private_hash[param]
> >   print public_fn("A")     # good:  prints 42
> >   x = private_hash["A"]    # works: oops, hash is in scope
>
> >  I'm not happy with that because I'd like to limit the scope of the
> >  private_hash variable so that it is known only inside public_fn.
>
> >  Of course, I could hide the hash like so:
>
> >   def public_fn(param):
> >     private_hash = dict( A=42, B=69 )
> >     return private_hash[param]
>
> >  yet I'm not happy with that either because of the repeated
> >  initialization the hash each time the function is called.
>
> >  What is the Pythonic equivalent of Perl's lexical scope, as
> >  illustrated by the code snippet above?
>
> Either
>
> _private_hash = dict( A=42, B=69)
>
> def public_fn(param):
>     return _private_hash[param]
>
> Or
>
> def public_fn(param, _private_hash = dict( A=42, B=69)):
>     return _private_hash[param]
>
> Is probably the pythonic equivalents.  Note that private_hash starts
> with an underscore which means it won't be exported from a module by
> default and it is a convention that it is private and shouldn't be
> fiddled with.  I'd probably go with the latter of the two examples.
>
> --
> Nick Craig-Wood <n... at craig-wood.com> --http://www.craig-wood.com/nick

Another approach is to just use a class to hold the data, and a class
method (AKA classmethod) to access the data:

# class definition
class my_util(object):
    _private_hash = { 'A':42,'B':69 }

    @classmethod
    def public_fn(cls,index):
        return cls._private_hash[index]

# usage
print my_util.public_fn('A')
print my_util.public_fn('B')

This keeps pretty close to the OP's intention. It does require you to
use the class name, but that's.....OK, and better than an anonymous
block IMHO.

Note: I'm a recovering Perl hacker.



More information about the Python-list mailing list