Python decorator for automatic binding __init__ arguments

14,355

Solution 1

http://code.activestate.com/recipes/551763-automatic-attribute-assignment/ is what you're looking for.

Also see What is the best way to do automatic attribute assignment in Python, and is it a good idea?

Solution 2

It's definitely possible, here's a somewhat naive implementation:

from functools import wraps

def lazy_init(init):
    import inspect
    arg_names = inspect.getargspec(init)[0]

    @wraps(init)
    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

Once you start having something besides attributes that map to properties, you're going to run into trouble though. You'll need at least some way to specify which args to initialize as properties... at which point it'll just become more hassle than it's worth.

Solution 3

For future reference for all others who encounter this question in the future (Python 3.7 or above): There is the dataclass decorator that does exactly this.

Example

from dataclasses import dataclass

@dataclass
class Person:
    name
    age
    address

# other methods...

Solution 4

You can either use data classes as of Python 3.7 like this:

from dataclasses import dataclass

@dataclass
class MyClass:
    var_1: str
    var_2: float

Or you can make use of the store_attr() method from the fastcore lib like this:

from fastcore.utils import store_attr

class MyClass:
    def __init__(self, var_1, var_2):
        store_attr()

Both result in the equivalent init method:

def __init__(self, var_1, var_2):
    self.var_1 = var_1
    self.var_2 = var_2
Share:
14,355
André Lima
Author by

André Lima

Updated on June 03, 2022

Comments

  • André Lima
    André Lima about 2 years

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

    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 there is any reason I'm not supposed to do it this way in the first place?

  • André Lima
    André Lima over 13 years
    Thanks. I realize that if the __init__ method is sophisticated it wouldn't be worth it, but the simple ones are so widespread that I think it would be nice to have something like that at hand.
  • Miles Rout
    Miles Rout almost 8 years
    Comments that are just a link to another resource are pretty bad form.
  • vijay shanker
    vijay shanker over 5 years
    requires changes for keyword arguments
  • rv.kvetch
    rv.kvetch over 2 years
    The dataclass approach seems sufficient enough for most cases :-)
  • rv.kvetch
    rv.kvetch over 2 years
    dv'ed because the implementation is unnecessarily complex. Its almost 2022, and we have dataclasses now!