Для переменной класса или переменной экземпляра
Держите. Да, это уродливый злой взлом. Да, объекту нужна переменная __dict__. Но эй, это аккуратный маленький лайнер!
def __init__(self):
self.__dict__.update(locals())
Конструктор может принимать аргументы любого типа.
class test(object):
def __init__(self, a, b, foo, bar=5)...
a = test(1,2,3)
dir(a)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'foo', 'bar', 'self']
Он также будет включать self, но вы можете легко удалить это или создать свою собственную функцию обновления, которая игнорирует self.
Вы можете использовать inspect.getargspec и инкапсулировать его как декоратор. Поиск необязательных аргументов и аргументов ключевого слова немного сложен, но это должно сработать:
def inits_args(func):
"""Initializes object attributes by the initializer signature"""
argspec = inspect.getargspec(func)
argnames = argspec.args[1:]
defaults = dict(zip(argnames[-len(argspec.defaults):], argspec.defaults))
@functools.wraps(func)
def __init__(self, *args, **kwargs):
args_it = iter(args)
for key in argnames:
if key in kwargs:
value = kwargs[key]
else:
try:
value = args_it.next()
except StopIteration:
value = defaults[key]
setattr(self, key, value)
func(self, *args, **kwargs)
return __init__
Вы можете использовать его так:
class Foo(object):
@inits_args
def __init__(self, spam, eggs=4, ham=5):
print "Foo(%r, %r, %r)" % (self.spam, self.eggs, self.ham)
Нет хорошего способа получить аргументы в виде списка, если они указаны индивидуально в сигнатуре функции. Вы, вероятно, сможете что-то сделать с помощью inspect или frame hacks, но это будет уродливее, чем просто изложить это, как вы это сделали.
Вы можете сделать это, используя самоанализ аргументов, но код будет длиннее, чем код, который вы пытаетесь заменить. Особенно если вы работаете с кВт, что, возможно, придется сделать.
Этот короткий код работает в большинстве случаев (улучшен по сравнению с примером неизвестных):
>>> class Foo:
... def __init__(self, labamba, **kw):
... params = locals().copy()
... del params['self']
... if 'kw' in params:
... params.update(params['kw'])
... del params['kw']
... self.__dict__.update(params)
Но это уродливый хакер, который делает код менее читабельным без какой-либо особой причины, кроме лени , так что не делай этого. А также, как часто у вас на самом деле есть классы, которые имеют более 5-6 параметров инициализации?
Функционально LINQ - это не что иное, как синтаксическое упрощение выражения монад. Linq to Objects (понимание списков - даже это уже было бы чрезвычайно полезно), о котором вы говорили, является лишь одним из возможных приложений этого (аналогичного List-Monad в Haskell).
Если вы пишете
from x in expr1
from y in expr2
select x + y
, это не что иное, как
do
x <- expr1
y <- expr2
return $ x + y
в Haskell.
Конкретные действия зависят от определенных пользователем Linq-провайдеров (методов расширения), из которых Linq .Enumerable
- это всего лишь одна реализация, включающая IEnumerable
s.
Предоставляя один, вы можете создать совершенно новую LINQ-семантику для своих типов.
Пример:
Как насчет насчет наследования от специального класса? Я думаю, что это более явный и гибкий способ:
class InitMe:
def __init__(self, data):
if 'self' in data:
data = data.copy()
del data['self']
self.__dict__.update(data)
class MyClassA(InitMe):
def __init__(self, ivar1, ivar2, ivar3 = 'default value'):
super().__init__(locals())
class MyClassB(InitMe):
def __init__(self, foo):
super().__init__({'xxx': foo, 'yyy': foo, 'zzz': None})
# or super().__init__(dict(xxx=foo, yyy=foo, zzz=None))
class MyClassC(InitMe):
def __init__(self, foo, **keywords):
super().__init__(keywords)
Попробуйте inspect.getargspec :
In [31]: inspect.getargspec(C.__init__)
Out[31]: ArgSpec(args=['self', 'ivar1', 'ivar2', 'ivar3', 'optional'],
varargs=None, keywords=None, defaults=(False,))
Мне больше всего нравится эта форма, не слишком длинная, с возможностью копирования и вставки, и с возможностью подкласса:
class DynamicInitClass(object):
__init_defargs=('x',)
def __init__(self,*args,**attrs):
for idx,val in enumerate(args): attrs[self.__init_defargs[idx]]=val
for key,val in attrs.iteritems(): setattr(self,key,val)