py3k feature proposal: field auto-assignment in constructors

André andre.roberge at gmail.com
Sun Jan 27 21:02:51 EST 2008


On Jan 27, 9:47 pm, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
> On Sun, 27 Jan 2008 19:13:27 -0500, Terry Reedy wrote:
>
> [snip]
>
> > class Test(object):
> >      @autoassign
> >      def __init__(self, _foo, _bar, baz):
> >          print 'baz =', baz
>
> [snip]
>
> > I think this version, with this name convention, is nice enough to
> > possibly go in the stdlib if there were an appropriate place for it.
> > Not sure where though.  If there were a classtools module....
>
> -1/2
>
> I don't like the name convention. _name already has a perfectly good
> convention: it's a private name, don't mess with it. That includes in
> function/method signatures. With your convention, _foo is public.
>
> I suppose you could write __foo for a private name, and ___foo for a
> *really* private name, relying on the decorator to strip one of the
> underscores. But counting all those underscores is a PITA, and what
> happens if you don't actually want that private name set as an instance
> attribute?
>
> As nice as this feature would be, and I vote +2 on the functionality, I
> wonder whether the amount of line noise in method definitions now will be
> approaching Perlish levels? We've got default values, type annotations
> (in Python3), *args and **kwargs, _ private names, and now we want to add
> auto-assignment.
>
> If we do get syntax support, I vote +1 on &foo, +1/2 on @foo, -1 on .foo
> and -1 on self.foo. (It's explicit, but it's long...).
>
> --
> Steven


Here's a version that
1. does not require new syntax
2. does not *necessarily* override the "_" prefix convention
3. follows the "Explicit is better than implicit" convention when
being called.

(Note: I do not necessarily recommend the "self_" choice)
========
from functools import wraps
from inspect import getargspec

def autoassign(prefix):
    def _autoassign(_init_):
         @wraps(_init_)
         def __autoassign(self, *args, **kwargs):
             argnames, _, _, _ = getargspec(_init_)
             for name, value in zip(argnames[1:], args):
                 if name.startswith(prefix):
                     setattr(self, name[len(prefix):], value)
             _init_(self, *args, **kwargs)

         return __autoassign
    return _autoassign

class Test(object):
     @autoassign('self_')
     def __init__(self, self_foo, self_bar, baz):
         print 'baz =', baz

t = Test(1, 2, 3)
print t.foo
print t.bar
print t.baz # raises an exception

=============
André



More information about the Python-list mailing list