Modify arguments between __new__ and __init__
Steven Bethard
steven.bethard at gmail.com
Sun Dec 23 01:01:50 EST 2007
Steven D'Aprano wrote:
> When you call a new-style class, the __new__ method is called with the
> user-supplied arguments, followed by the __init__ method with the same
> arguments.
>
> I would like to modify the arguments after the __new__ method is called
> but before the __init__ method, somewhat like this:
>
>
>>>> class Spam(object):
> ... def __new__(cls, *args):
> ... print "__new__", args
> ... x = object.__new__(cls)
> ... args = ['spam spam spam']
> ... return x
> ... def __init__(self, *args):
> ... print "__init__", args # hope to get 'spam spam spam'
> ... return None
>
> but naturally it doesn't work:
>
>>>> s = Spam('spam and eggs', 'tomato', 'beans are off')
> __new__ ('spam and eggs', 'tomato', 'beans are off')
> __init__ ('spam and eggs', 'tomato', 'beans are off')
>
> Is there any way to do this, or am I all outta luck?
You can really only achieve this by writing a metaclass. When a new
object is created, what's first called is the __call__ method of the
type object. This basically looks like::
def __call__(cls, *args, **kwargs):
obj = cls.__new__(cls, *args, **kwargs)
obj.__init__(*args, **kwargs)
return obj
Hopefully that explains the behavior you're seeing. If you want
different behavior than this, you can change __call__ by defining your
own metaclass with a different __call__ method, for example::
>>> class SpamMeta(type):
... def __call__(cls, *args, **kwargs):
... obj = cls.__new__(cls)
... obj.__init__('spam spam spam')
... return obj
...
>>> class Spam(object):
... __metaclass__ = SpamMeta
... def __new__(cls, *args):
... print '__new__', args
... return object.__new__(cls)
... def __init__(self, *args):
... print '__init__', args
...
>>> Spam()
__new__ ()
__init__ ('spam spam spam',)
<__main__.Spam object at 0x00E756F0>
Hope that helps,
STeVe
More information about the Python-list
mailing list