Generic constructors and duplication of internal Python logic
Peter Otten
__peter__ at web.de
Tue Apr 20 03:51:39 EDT 2004
John J. Lee wrote:
> Peter Otten <__peter__ at web.de> writes:
>
>> John J. Lee wrote:
> [...]
>> You could use a noop method check_attrs() to define the argspec.
>> check_attrs() is then called from the mixin's __init__() just to check
>> that the parameters comply.
>>
>> import inspect
>>
>> def make_attrspec(f):
>> a = inspect.getargspec(f)
>> names = a[0]
>> if names[0] in ["self", "cls"]:
>> # XXX for now relies on naming convention
>> del names[0]
>> defaults = a[3]
>> for i in range(-1, -len(defaults)-1, -1):
>> names[i] = names[i], defaults[i]
>> return names
>>
>> class ArgsMixin:
>> def __init__(self, *args, **kwds):
>> self.check_attrs(*args, **kwds)
>>
>> class Blah(ArgsMixin):
>> def check_attrs(self, foo, bar, baz, optional1="first",
>> optional2="second"):
>> pass
>> attr_spec = make_attrspec(check_attrs)
>
> Clever. But how to get __init__ to assign the arguments to the
> instance?
>
> b = Blah(foo=1, bar=2, optional1=4)
> assert b.foo, b.bar, b.optional1 = 1, 2, 4
>
>
> That half of the problem is missing in your solution.
I'll give it a try (untested):
class ArgsMixin:
def __init__(self, *args, **kwds):
self.check_attrs(*args, **kwds)
# positionals provided
for n, v in zip(self.attr_spec, args):
setattr(self, n, v)
# positionals using defaults
for nv in self.attr_spec[len(args):]:
if not isinstance(nv, basestring):
n, v = nv
if not n in kwds:
setattr(self, n, v)
# keyword args
for n, v in kwds.iteritems():
setattr(self, n, v)
The clumsy basestring check could be avoided if you either split attr_spec
in the tuple/non-tuple parts or precalculate the first non-tuple position.
Peter
More information about the Python-list
mailing list