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 -- http://mail.python.org/mailman/listinfo/python-list