Steven D'Aprano wrote: > On Fri, 12 Jun 2015 16:53:08 +0100, Paulo da Silva wrote: > >> I would like to do something like this: >> >> class C: >> def __init__(self,**parms): >> ... >> >> c=C(f1=1,f2=None) >> >> I want to have, for the object >> self.f1=1 >> self.f2=None >> >> for an arbitrary number of parameters. >> >> What is the best way to achieve this? > > > Others have suggested that you update the instance dict with the keyword > parameters: > > self.__dict__.update(parms) > > > But I suggest that you should be very careful with this technique, > because it can lead to surprising problems and bugs in your code. If your > class has methods (and what sort of class doesn't have methods?), this > will override them and lead to mysterious failures in your code: > > instance = C(a=1, b=2, method=3) > # much later > result = instance.method(args) # will raise exception > > > You should use SimpleNamespace, as Peter suggests, but *not* subclass it. > If you subclass it and add methods: > > class C(SimpleNamespace): > def foo(self, arg): > print("called foo") > > > then you risk overriding foo method, as above. If you don't add methods, > there is no need to subclass.
I sometimes do it anyway if only to get a meaningful class name. > Instead, use composition: your class should *contain* a SimpleNamespace, > not *be* one: > > class C: > def __init__(self, **param): > self.ns = SimpleNamespace(param) **param > def __getattr__(self, attrname): > return getattr(self.ns, attrname) > def foo(self, arg): > print("called foo") > > > instance = C(a=1, b=2, foo=3) > # later > instance.foo("x") # prints "called foo" >>> c = C(ns=42) >>> assert c.ns == 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError Yes, it's less likely, but now that the OP has two convenient ways to produce a name clash I think it's time to repeat that there is one bullet- proof approach: use a dict ;) > The special method __getattr__ only runs if the attribute name is not > found in the usual way, so the method foo will continue to be found and > not be overridden by the param foo. -- https://mail.python.org/mailman/listinfo/python-list