用于自动绑定__init__参数的Python装饰器

时间:2011-02-19 01:49:26

标签: python initialization decorator

有没有办法自动绑定self方法的__init__(某些)参数?

我的意思是:

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

...而不是:

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

我想知道在这种情况下人们是否已经使用了类似的东西。或者有什么理由我不应该首先这样做?

5 个答案:

答案 0 :(得分:5)

这绝对是可能的,这是一个有点天真的实现:

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

一旦你开始拥有映射到属性的属性之外的东西,你就会遇到麻烦。你至少需要一些方法来指定哪些args初始化为属性......在这一点上它会变得比它的价值更麻烦。

答案 1 :(得分:3)

答案 2 :(得分:0)

这里以最简单的形式出现:

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
>>> q.a, q.b
(1, 2)

考虑制作一个类装饰器来覆盖__str__

答案 3 :(得分:0)

我创建的initify.py :)它完全符合您的期望。

for (int i = 0; i < object.size(); i++) {
     if (object.get(i).removed)
          object.remove(i);
}

或使用默认值:

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

甚至不包括继承:

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

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

答案 4 :(得分:0)

供以后将来遇到此问题的所有其他人(Python 3.7或更高版本)参考: 有dataclass装饰器可以做到这一点。

示例

@dataclass
class Person:
    name
    age
    address

# other methods...