Perl vs. Python question...

Steven W. Orr steveo at syslang.net
Sun Jul 12 15:56:25 EDT 2009


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 07/11/09 23:44, quoth Paul Lussier:
> 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?

In the Python Coookbook, on (my) page 252 is a section called Section 6.8:
"Avoiding Boilerplate Accessors for Properties".

http://www.ubookcase.com/book/Oreilly/Python.Cookbook.2nd.edition/0596007973/pythoncook2-chp-6-sect-8.html

The code they provide is this:

def xproperty(fget, fset, fdel=None, doc=None):
    if isinstance(fget, str):
        attr_name = fget
        def fget(obj): return getattr(obj, attr_name)
    elif isinstance(fset, str):
        attr_name = fset
        def fset(obj, val): setattr(obj, attr_name, val)
    else:
        raise TypeError, 'either fget or fset must be a str'
    return property(fget, fset, fdel, doc)

but the discussion is important to read and fully understand before you think
you can just plug it in.

- --
Time flies like the wind. Fruit flies like a banana. Stranger things have  .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkpaP+kACgkQRIVy4fC+NyRqtQCeLV5oscJqOGQ0zME7KXjvM8n2
HZsAn1OcpB0aif6K1rTbchwdV7GDzn7k
=gJni
-----END PGP SIGNATURE-----


More information about the gnhlug-discuss mailing list