Python-декоратор для автоматического связывания аргументов __init__ - PullRequest
8 голосов
/ 19 февраля 2011

Есть ли способ автоматически связать 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
        ...

Интересно, есть ли что-то подобное, что люди уже используют в таких случаях.Или есть какая-то причина, по которой я не должен делать это таким образом?

Ответы [ 4 ]

5 голосов
/ 19 февраля 2011

Это определенно возможно, вот несколько наивная реализация:

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

Как только вы начнете иметь что-то помимо атрибутов, которые сопоставляются со свойствами, вы столкнетесь с проблемами.Вам понадобится хотя бы какой-то способ указать, какие аргументы инициализировать в качестве свойств ... в этот момент он просто станет более хлопотным, чем стоит.

0 голосов
/ 25 мая 2015

initify.py созданный мной :) он делает именно то, что вы ожидаете.

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

или со значениями по умолчанию:

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

или даже без наследования:

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

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

0 голосов
/ 19 февраля 2011

Вот, пожалуйста, в простейшей форме:

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__.

...