Я иногда делаю это для классов, которые действуют «как куча», то есть они имеют кучу настраиваемых атрибутов:
class SuperClass(object):
def __init__(self, **kw):
for name, value in kw.iteritems():
if not hasattr(self, name):
raise TypeError('Unexpected argument: %s' % name)
setattr(self, name, value)
class SubClass(SuperClass):
instance_var = None # default value
class SubClass2(SubClass):
other_instance_var = True
@property
def something_dynamic(self):
return self._internal_var
@something_dynamic.setter # new Python 2.6 feature of properties
def something_dynamic(self, value):
assert value is None or isinstance(value, str)
self._internal_var = value
Тогда вы можете позвонить SubClass2(instance_var=[], other_instance_var=False)
, и он будет работать без определения __init__
ни в одном из них. Вы также можете использовать любую собственность. Хотя это позволяет вам перезаписывать методы, которые вы, вероятно, не захотите (так как они возвращают True для hasattr()
, как переменная экземпляра).
Если вы добавите property
или другой дескриптор, он будет работать нормально. Вы можете использовать это для проверки типов; в отличие от проверки типов в __init__
, она будет применяться каждый раз, когда значение обновляется. Обратите внимание, что вы не можете использовать любые позиционные аргументы для них, если вы не переопределите __init__
, поэтому иногда то, что будет естественным позиционным аргументом, не будет работать. formencode.declarative охватывает эту и другие проблемы, возможно, с большой тщательностью, я бы не советовал вам пытаться (оглядываясь назад, я не думаю, что это того стоит).
Обратите внимание, что любой рецепт, который использует self.__dict__
, не будет учитывать свойства и дескрипторы, и если вы используете их вместе, вы получите странные и неожиданные результаты. Я только рекомендую использовать setattr()
для установки атрибутов, никогда self.__dict__
.
Кроме того, этот рецепт не дает очень полезной подписи, в то время как некоторые из них, которые делают самоанализ фрейма и функции, делают. С некоторой работой можно динамически генерировать __doc__
, который проясняет аргументы ... но опять же я не уверен, что выигрыш стоит добавить больше движущихся частей.