[Python-ideas] Simple class initialization

dag.odenhall at gmail.com dag.odenhall at gmail.com
Sat Apr 16 14:08:45 CEST 2011


On 16 April 2011 13:50, Adam Matan <adam at matan.name> wrote:
> 0. Abstract
> ===========
> A class initialization often begins with a long list of explicit variable
> declaration statements at the __init__() method. This repetitively copies
> arguments into local data attributes.
> This article suggests some semi-automatic techniques to shorten and clarify
> this code section. Comments and responses are highly appreciated.
> 1. Credit
> =========
> The idea emerged from my question at stackoverflow.com. I would like to
> thank
> all those who answered and commented on that thread.
> http://stackoverflow.com/questions/1389180
> 2. The problem
> ==============
> Consider the following class:
>         class Process:
>             def __init__(self, pid, ppid, cmd, fd, reachable, user):
> If the instance needs to hold these arguments internally, local data
> attributes
> are declared and the value of the argument is being copied, using two
> mainstream
> notations:
> a.
>                 self.pid=pid
>                 self.ppid=ppid
>                 self.cmd=cmd
>                 self._fd=fd
>                 self.reachable=reachable
>                 self.user=user
> b.
>                 self.pid, self.ppid, self.cmd, self._fd, self.reachable,
> self.user = pid, ppid, cmd, fd, reachable, user
> a. takes an unreasonable amount of lines and has a repetative form.
> b. is long and prone to errors, especially when the argument list changes
>    during development.
> 3. Solution outline
> ===================
> 1. Generally comply with the Zen of Python.
> 1. Explicit. The instance should not store any value unless told.
> 2. Short.
> 3. Backward compatible. Current Class syntax should work with the
>    new solution.
> 4. Readable and intuitive.
> 5. Flexible. There should be a way to store any given subset of
>    the arguments.
> 6. Allow storage of "private" variables by adding a single or double
>    underscore before the variable name.
> 4. Solutions
> ============
> 4.1 Decorator
> -------------
> Nadia Alramli suggested this at the aforementiond thread at stackoverflow:
>         from functools import wraps
>         import inspect
>         def initializer(fun):
>             names, varargs, keywords, defaults = inspect.getargspec(fun)
>             @wraps(fun)
>             def wrapper(self, *args):
>                 for name, arg in zip(names[1:], args):
>                     setattr(self, name, arg)
>                 fun(self, *args)
>             return wrapper
>         class Process:
>             @initializer
>             def __init__(self, pid, ppid, cmd, fd, reachable, user)
> Pros:
>     Simple, short, explicit and intuitive.
>     Easy to add to the standard library, fully backward-compatible.
> Cons:
>     Stores all arguments.
>     Does not support private data attributes notation (underscore prefix).
> See
> http://stackoverflow.com/questions/1389180/python-automatically-initialize-instance-variables/1389216#1389216
>
> 4.2. Argument tagging
> ---------------------
> Arguments that needed to be stored within the instance could be marked with
> a
> special character, e.g. '~'. The character would be placed after the
> argument
> name for private variables:
>         class Process:
>             def __init__(self, ~pid, ~ppid, ~cmd, fd~, ~reachable, ~user)
> Pros:
>     Simple, short and explicit.
>     Can store any subset of the arguments.
>     Supports private variable notation.
> Cons:
>     Not intuitive. Changes the method signature and might be confusing.
>
> 4.3 Standard function
> ---------------------
> A function will be called to store the argument as data attributes.
>         class Process:
>             def __init__(self, pid, ppid, cmd, fd, reachable, user)
>                 acquire(pid, ppid, cmd, reachable, user)
>                 acquire(fd, prefix='_')
> Possible keywords can ba acquire, store, absorp.
> Pros:
>     Explicit, clear and intuitive.
> Cons:
>     Long - especially if more than a single prefix is used.
> 4.4 Initialization list
> -----------------------
> The argument list would include the name of the local data attribute, a
> separator, and the argument name.
>         class Process:
>             def __init__(self, pid:pid, ppid:ppid, cmd:cmd, _fd:fd,
> reachable:reachable, user:user)
>             """ pid, ppid, cmd, reachable and user are stored as data
> properties
>                 with the same name. fd is stored as _fd."""
> Or:
>         class Process:
>             def __init__(self, :pid, :ppid, :cmd, _fd:fd, :reachable, :user)
>             """Same, but local data attributes with the same name as
> arguments
>                would be stored without stating their name twice."""
> This is a developed argument tagging (4.2).
> Pros:
>      See 4.2
> Cons:
>      Alters the method signature
>      Not intuitive.
>
> Looking forward for comments,
> Adam matan


class Process:

    # Defaults and documentation as class attributes
    pid = None

    def __init__(self, **kwargs):
        for k, v in kwargs.iteritems():
            setattr(self, k, v)



More information about the Python-ideas mailing list