Python decoder to automatically bind __init__ arguments

Is there a way to automatically bind the __init__ method arguments to self (some)?

I mean something like:

 class Person: @lazy_init def __init__(self, name, age, address): ... 

... instead of:

 class Person: def __init__(self, name, age, address): self.name = name self.age = age self.address = address ... 

I wonder if there is something similar that people already use in such cases. Or is there some reason why I should not do this in the first place?

+7
source share
4 answers

This is definitely possible, here is a somewhat naive implementation:

 def lazy_init(init): import inspect arg_names = inspect.getargspec(init)[0] def new_init(self, *args): for name, value in zip(arg_names[1:], args): setattr(self, name, value) init(self, *args) return new_init class Person: @lazy_init def __init__(self, name, age): pass p = Person("Derp", 13) print p.name, p.age 

As soon as you start to have something besides the attributes that appear in the properties, you are faced with a problem. You will need at least some way to indicate which arguments are initialized as properties ... at this point it will just become more complex than it costs.

+4
source

Here it goes in its simplest form:

 def lazy_init(*param_names): def ret(old_init): def __init__(self, *args, **kwargs): if len(args) > len(param_names): raise TypeError("Too many arguments") for k in kwargs: if k not in param_names: raise TypeError("Arg %r unexpected" % k) for par, arg in zip(param_names, args): setattr(self, par, arg) for par, arg in kwargs.items(): setattr(self, par, arg) old_init(*args, **kwargs) return __init__ # return ret class Q(object): @lazy_init("a", "b") def __init__(self, *args, **kwargs): print "Original init" >>> q = Q(1, 2) Original init >>> qa, qb (1, 2) 

Consider creating a class decorator to cover __str__ too.

0
source

initify.py created by me :) it does exactly what you expect.

 class Animal: @init_args(exclude=["name"]) def __init__(self, name): pass 

or with default values:

 class Animal: @init_args def __init__(self, name="Default name"): pass 

or even excluding inheritance:

 class Dog(Animal): @init_args(exclude=["name"]) def __init__(self, species): pass 

https://github.com/prankymat/initify.py

0
source

All Articles