Автоматически созданный конструктор Python

У меня есть бесчисленные классы Python из различных проектов из SQLAlchemy (и пара из Pygame), и я недавно заметил шаблон во многих из них: их конструкторы всегда делали что-то вроде этого:

class Foo(Base): def __init__(self, first, last, email, mi=""): self.first = first self.last = last self.email = email self.mi = mi 

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

Мне кажется, что это повторение не нужно и подвержено человеческой ошибке при изменении.

Это приводит меня к вопросу здесь: возможно ли автоматически генерировать такую ​​функцию __init__(self, ...) , желательно без обхода с помощью байт-кода CPython или использования шаблонов / макросов для изменения самого исходного файла?

3 Solutions collect form web for “Автоматически созданный конструктор Python”

Возможно, вы можете сделать это с помощью Metlasslasses. Вот пример метакласса, который переопределяет __init__() : Python Class Decorator

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

 # This is the mataclass-defined __init__ def auto_init(self, *args, **kwargs): for arg_val, arg_name in zip(args, self.init_args): setattr(self, arg_name, arg_val) # This would allow the user to explicitly specify field values with named arguments self.__dict__.update(kwargs) class MetaBase(type): def __new__(cls, name, bases, attrs): attrs['__init__'] = auto_init return super(MetaBase, cls).__new__(cls, name, bases, attrs) class Base(object): __metaclass__ = MetaBase # No need to define __init__ class Foo(Base): init_args = ['first', 'last', 'email', 'mi'] 

Проверьте namedtuple:

 >>> from collections import namedtuple >>> Foo = namedtuple("Foo", "first last email mi") >>> f = Foo("Alfred", "Neumann", "aen@madmagazine.com", "E") >>> f Foo(first='Alfred', last='Neumann', email='aen@madmagazinecom', mi='E') 

Вы можете сделать что-то вроде этого:

 class Foo(Base): def __init__(self, **kwargs): self.__dict__.update(kwargs) 

Одна из проблем с этим заключается в том, что нет гарантии, что все экземпляры будут иметь одинаковые элементы. Другая проблема – теперь все конструкторы должны быть вызваны с помощью аргументов ключевого слова.

Python - лучший язык программирования в мире.