[Python-ideas] Simple class initialization

Nathan Schneider nathan at cmu.edu
Sat Apr 16 19:23:13 CEST 2011


I like the initializer decorator. Here's a version that (1) handles keyword
argument defaults, and (2) allows only a subset of arguments to be stored
via decorator arguments:

def initializer(*selectedArgs):
    def wrap(fun):
        names, varargs, varkwargs, defaults = inspect.getargspec(fun)
        @wraps(fun)
        def wrapper(self, *args, **kwargs):
            d = dict(zip(names[-len(defaults):],defaults))
            d.update(dict(zip(names[1:], args)))
            d.update(kwargs)
            for a in (selectedArgs if len(selectedArgs)>0 else d.keys()):
                assert a in names,'Invalid parameter name: {}'.format(a)
                assert a in d,'Missing required argument: {}'.format(a)
                setattr(self, a, d[a])
            fun(self, *args, **kwargs)
        return wrapper
    return wrap

class Process1:
    @initializer()
    def __init__(self, pid, ppid, cmd, fd, reachable=True, user=None)

class Process2:
    @initializer('pid','ppid','user') # only store these 3; self.cmd will
trigger an error
    def __init__(self, pid, ppid, cmd, fd, reachable=True, user=None)

Nathan

On Sat, Apr 16, 2011 at 12:25 PM, Ethan Furman <ethan at stoneleaf.us> wrote:
> dag.odenhall at gmail.com wrote:
>>
>> 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.
>
> [snippers]
>
>> class Process:
>>
>>    # Defaults and documentation as class attributes
>>    pid = None
>>
>>    def __init__(self, **kwargs):
>>        for k, v in kwargs.iteritems():
>>            setattr(self, k, v)
>
> I like the initialiser function myself:
>
> 8<-------------------------------------------------------------
> def acquire(obj, kwargs):
>    Missing = object()
>    for kw, val in kwargs.items():
>        name = '_'+kw
>        attr = getattr(obj, name, Missing)
>        if attr is Missing:
>            name = kw
>            attr = getattr(obj, name, Missing)
>        if attr is not Missing:
>            setattr(obj, name, val)
>
> class Process:
>    pid = None
>    ppid = None
>    cmd = None
>    reachable = None
>    user = None
>    _fd = None
>    def __init__(self, pid, ppid, cmd, fd, reachable, user):
>        acquire(self, locals())
>        print(self.pid)
>        print(self.ppid)
>        print(self.cmd)
>        print(self.reachable)
>        print(self.user)
>        print(self._fd)
>
> if __name__ == '__main__':
>    p = Process(9, 101, 'cd /', 0, 'yes', 'root')
> 8<-------------------------------------------------------------
>
> Don't think it needs to be in the stdlib, though.
>
> ~Ethan~
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20110416/9c1cd101/attachment.html>


More information about the Python-ideas mailing list