Generic constructors and duplication of internal Python logic
Robert Brewer
fumanchu at amor.org
Fri Apr 23 13:00:02 EDT 2004
Peter Otten wrote:
> def setLocals(d, selfName="self"):
> self = d.pop(selfName)
> for n, v in d.iteritems():
> setattr(self, n, v)
>
> class Demo(object):
> def __init__(self, foo, bar, baz=2, bang=3):
> setLocals(locals())
*Very* nice and clean.
John, if you still want the mixin (to avoid have to call setLocals in
every __init__, you could try a mixin like this (tested just enough to
post without egg on my face):
class ArgMixin(object):
def __new__(cls, *args, **kwargs):
inst = object.__new__(cls, *args, **kwargs)
initargs = list(cls.__init__.func_code.co_varnames)
# Remove 'self' from initargs
initargs.pop(0)
defaults = list(cls.__init__.func_defaults)
# Set provided positional arguments as attributes of instance
for arg in args:
name = initargs.pop(0)
setattr(inst, name, arg)
# Set keyword arguments as attributes of instance,
# using defaults if no value was passed.
while initargs:
name = initargs.pop(0)
default = defaults.pop(0)
setattr(inst, name, kwargs.get(name, default))
return inst
class Demo(ArgMixin):
def __init__(self, foo, bar, baz=2, bang=3):
pass
...you would have to be careful when/if overriding __new__ in a
subclass. Also, __init__ can still change those attributes. I'm sure
someone will find something wrong with it* ;) but the idea is sound, and
uses some of Python's "internal logic" that you mentioned.
Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org
* For example, I didn't chase down funky calls like Demo(bar=3,
foo="d'oh!"), which exhaust the defaults list.
More information about the Python-list
mailing list