[Tutor] Metaclass programming
Kent Johnson
kent37 at tds.net
Tue Sep 4 14:02:59 CEST 2007
Orest Kozyar wrote:
> I have the following code:
>
> class meta(type):
>
> def __call__(cls, *args, **kwargs):
> argnames = inspect.getargspec(cls.__init__)[0]
> for i, value in enumerate(args):
> kwargs[argnames[i]] = value
This could be written
kwargs.update(zip(argnames, args))
> return type.__call__(cls, kwargs)
You are passing kwargs as a positional argument to __call__(); i.e.
passing the dict as an ordinary parameter. To use kwargs as the keyword
dict for the call, use the syntax
type.__call__(cls, **kwargs)
> class test(object):
>
> __metaclass__ = meta
>
> def __init__(self, x, y, **kwargs):
> pass
>
> However, inspect.getargspec(cls.__init__) appears to return only the
> arguments of the meta __init__ rather than the test __init__. Is there any
> way I can get access to the test __init__ function from the metaclass?
It works for me:
import inspect
class meta(type):
def __call__(cls, *args, **kwargs):
print inspect.getargspec(cls.__init__)
return type.__call__(cls, *args, **kwargs)
class test(object):
__metaclass__ = meta
def __init__(self, x, y, **kwargs):
pass
test(1, 2)
prints (['self', 'x', 'y'], None, 'kwargs', None)
I think the problem is elsewhere in your code. When I use
return type.__call__(cls, kwargs)
I get
TypeError: __init__() takes exactly 3 arguments (2 given)
because test.__init__() is still expecting the two required positional
arguments.
Why are you doing this?
Kent
More information about the Tutor
mailing list