Perl vs. Python question...

Paul Lussier p.lussier at comcast.net
Sat Jul 11 23:44:28 EDT 2009


Hi Folks,

How do I create dynamically created methods in python classes?

For example, if I have a number of member variables which I want to get
or set, I don't want to have to create getters and setters for each
attribute, since the code would largely be the same, just the variable
I'm dealing with would be different.

In perl, I can use the AUTOLOAD feature to dynamically create methods,
something like this:

  sub AUTOLOAD {
    my ($self, @args) = @_;
    my $method = $AUTOLOAD;
    $method =~ s/.*:://;
    if ($method ne 'DESTROY') {
      # Return the structure/value pointed to by $self->{KEY}, or, set it
      # if it's not a ref to something else.
      if (exists $self->{"_$method"} && !ref($self->{"_$method"})) {
        eval("*$AUTOLOAD = "
             . "sub {"
           . "  my (\$self, \$value) = assertMinMaxArgs(1, 2, \@_);"
             . "  if (\$value) {"
             . "    \$self->{\"_\$method\"} = \$value;"
             . "  }"
             . "  return \$self->{\"_\$method\"}"
             . "}");
      }
      goto &$AUTOLOAD;
    }
  }    

What this AUTOLOAD sub does is this:

 - First, it strips everything before the :: leaving just the methodname
   (in perl, method names look like: CLASS::method() )
 - Then, it looks to see if there exists a member variable
   $self->{_<foo>}, and that it's not a reference to something
 - Then, it creates an anonymous sub (== a lambda in python I think)
   Each anonymous sub looks like this:

    sub {
      my ($self, $value) = assertMinMaxArgs(1, 2, @_);
      if ($value) {
         $self->{_$method} = $value;
      }
      return $self->{_$method}

Essentially, it works like this.  If I have a member variable _foo, and
I want to either set or get _foo, I call a method $self->foo().  If I
call it as $self->foo(bar), the _foo gets set to bar, otherwise, I get
back the current value of _foo.  So, the anonymous sub above, gets
re-written as:

    sub foo {
      my ($self, $value) = assertMinMaxArgs(1, 2, @_);
      if ($value) {
         $self->{_foo} = $value;
      }
      return $self->{_foo}

I can basically create 1 method which will automagically create for me,
getter and setter methods for any member variable I create in my class.
(this is extremely similar, if not identical, to lisp macros!)

For some reason I didn't think python had this capability, but someone
mentioned to me it did, but I'm not quite sure how I'd write it.

Does anyone have any ideas?

--
Thanks,
Paul


More information about the gnhlug-discuss mailing list