The Artima Developer Community
Sponsored Link

Python Buzz Forum
Reducing boilerplate code in __init__

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Ian Bicking

Posts: 900
Nickname: ianb
Registered: Apr, 2003

Ian Bicking is a freelance programmer
Reducing boilerplate code in __init__ Posted: Jul 15, 2005 2:40 PM
Reply to this message Reply

This post originated from an RSS feed registered with Python Buzz by Ian Bicking.
Original Post: Reducing boilerplate code in __init__
Feed Title: Ian Bicking
Feed URL: http://www.ianbicking.org/feeds/atom.xml
Feed Description: Thoughts on Python and Programming.
Latest Python Buzz Posts
Latest Python Buzz Posts by Ian Bicking
Latest Posts From Ian Bicking

Advertisement

In Dr. Dobb's Python-URL I came upon this thread proposing a change to Python (either syntax or builtin) to facilitate this general pattern:

class Foo(object):
    def __init__(self, a, b=5, c=None):
        self.a = a
        self.b = b
        self.c = c or {}

There's two proposals, basically. One is syntax:

class Foo(object):

def __init__(self, .a, .b=5, c=None):
self.c = c or {}

By putting (that very little character) . in front of an argument, you imply that it should be assigned to self. The other builtin is:

class Foo(object):
    def __init__(self, a, b=5, c=None):
        adapt_init_args(self, locals())
        # reassignment fixup:
        self.c = c or {}

Using frame hacks, you could easily allow adapt_init_args() to work without arguments. Someone additionally noted a recipe that putting _ in front of the a and b to hint to adapt_init_args which arguments should become instance variables (though that messes up the signature).

There's lots of ways to do this. For instance, I regularly use:

class Foo(object):
    def __init__(self, **kw):
        for name, value in kw.items():
            setattr(self, name, value)

But that can allow typos too easily. So sometimes I set defaults as class variables, and test for hasattr(), and raise an error if an extraneous variable is found. It also doesn't allow for positional arguments. Or mutable defaults, since those defaults end up as class variables, and unwittingly mutating values for all instances will mess you up.

This is one those There's More Than One Way To Do It cases. Though I'm not excited about the syntax proposal, it's addresses a real problem. Clever hacks don't cut it. There's lots of them. They work differently. You can't necessarily recognize them each right away. They each have flaws -- some quite significant.

So far the only hack that seems decent to me (a hack that does not exist to my knowledge) would be a decorator that works with the _ prefixes on variables (using something like **_kw to replicate the setattr thing I show above). This should be a clever decorator because it needs to:

  • Read the signature of the enclosed function.
  • Modify that signature, removing _ prefixes, so that you can do Foo(a=10) instead of Foo(_a=10).
  • Reveal the "proper" (underscore-less) signature to introspection tools.
  • Allow positional calling of keyword arguments, just like normal functions.

A decorator for this is okay -- better than most of the things people have been proposing -- but not terribly pleasing. It's magical, but a kind of hidden and mysterious magic. It bridges an implementation and an external interface, but if you don't know how the decorator works then you won't understand the disconnect.

I'm not sure what syntax I'd want. I'm not sure if syntax is feasible here -- there's limited room in a function signature. But I think people who say that syntax is always the wrong answer, or that this isn't an issue, are just too set in their ways to see the issue. Python's strength -- particularly compared to the other dynamic languages -- is in the consistency with which people use it. This is how Python is different from Lisp and Ruby (and actually how it is similar to Smalltalk). I think many people (especially the perennial skeptics in comp.lang.python) underappreciate this.

Read: Reducing boilerplate code in __init__

Topic: Google AdSense Previous Topic   Next Topic Topic: On ethanol

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use