On Sep 27, 6:16 pm, Terry Reedy <[EMAIL PROTECTED]> wrote: > Aaron "Castironpi" Brady wrote: > >>>> class A(type): > > ... def __call__( self, *ar ): > > ... print 'call', self, ar > > ... > >>>> class B(object): > > ... __metaclass__= A > > ... > >>>> B(3) > > call <class '__main__.B'> (3,) > > > Overriding the __call__ method of 'type' has the effect of giving you > > a static __call__ method on a class-- a method which doesn't need an > > instance to call. Your behavior may be counterintuitive though, to > > someone who wants to instantiate 'B', in this case, and proceed like a > > normal object. That is, they want to call a generic class and use it, > > and also expect instances of B to behave as B. You can't have both, > > so either return B from B.__new__, or, to instantiate B, take the long > > way and call B.__new__ directly. > > >>>> B.__new__(B) > > <__main__.B object at 0x009FDB70> > > > Has anyone stepped through the C code to find out when the decision is > > made to call which function, B.__new__ or A.__call__, when B is > > called? > > For Python coded objects, ob(*args) in code translates to internal > execution of type(ob).__call__(ob, *args) (without further > translation!). The interpreter compiles a statement at a time, without > looking back to do type inferencing, and so does not know what type is > being called or if it is even callable. > > For B, B(*args) == type(B).__call__(B, *args) == A.__call__(B, *args). > So there is no decision. > > For C coded objects, I believe ob(*args) in Python code translate to a C > call of the C equivalent of type(ob).tp_call (or something like that). > From observation, type.tp_call acts something like this: > > def __call__(cls, *args): > if cls == type: > if len(*args): > return arg[0].__class__ > elif len(*args) == 3: > return type.__new__(type, *args) # or maybe not pass type? > else: > raise TypeError('type() takes 1 or 3 arguments') > else: > return cls.__new__(cls, *args) > > So, for a normal class C (an instance of type), type.__call__ calls > C.__new__. > > Terry Jan Reedy
Oh, I see. Then it's the class statement that calls type.__new__. class A: ... -> A= type( 'A', ... ) -> A= type.__call__( type, 'A', ... ) -> A= type.__new__( type, 'A', ... ) Plus an iteration over the contents of 'namespace', to search for properties that themselves have a __get__ method. And returns an unboundmethod instance "of" it, for a value of "of" that's hard to concentrate on. I jest. Perhaps what Steven is looking for is a subclass of 'type' that does not give this default behavior of 'unboundmethoding' everything it can. That is, defaulting to 'staticmethod' or 'classmethod', and perhaps offering a 'boundmethod' decorator for the exceptions. For the case of '__call__', which he does want to control, that could merely call B.__call__, instead of B.__new__. Untested: >>> class A(type): ... def __call__( self, *ar ): ... return self.__call__( *ar ) or ... return self.__call__( self, *ar ) Which would come through to 'B' as: >>> class B(object): ... __metaclass__= A ... def __call__( cls, *ar ). This is because self == B in the example. This makes me scowl. Very odd. -- http://mail.python.org/mailman/listinfo/python-list