staticmethod vs metaclass

Robin Becker robin at reportlab.com
Wed Aug 11 13:27:07 EDT 2004


A colleague wanted to initialize his class __new__ and tried code resembling this

#######################1
class Metaclass (type):
     def __init__(cls, name, bases, *args, **kwargs):
         super(Metaclass, cls).__init__(cls, name, bases, *args, **kwargs)
         print  'cls=',cls, cls.__new
         cls.__new__ = staticmethod(cls.__new)

     def __new(self,cls,*args):
         print 'new(',self,cls,args,')'
         return object.__new__(cls,*args)

class A:
     __metaclass__ = Metaclass
     def __init__(cls,*args):
         print '__init__(',cls,args,')'
A(3,4,5)
#######################
cls= <class '__main__.A'> <bound method Metaclass.__new of <class '__main__.A'>>
new( <class '__main__.A'> <class '__main__.A'> (3, 4, 5) )
__init__( <__main__.A object at 0x008D0AB0> (3, 4, 5) )
#######################

We wanted to eliminate the extra self argument in the constructed class __new__
so tried
#######################2
class Metaclass (type):
     def __init__(cls, name, bases, *args, **kwargs):
         super(Metaclass, cls).__init__(cls, name, bases, *args, **kwargs)
         print  'cls=',cls, cls.__new
         cls.__new__ = staticmethod(staticmethod(cls.__new))

     def __new(cls,*args):
         print 'new(',cls,args,')'
         return object.__new__(cls,*args)

class A:
     __metaclass__ = Metaclass
     def __init__(cls,*args):
         print '__init__(',cls,args,')'
A(3,4,5)
#######################
cls= <class '__main__.A'> <bound method Metaclass.__new of <class '__main__.A'>>
Traceback (most recent call last):
   File "mmm.py", line 15, in ?
     A(3,4,5)
TypeError: 'staticmethod' object is not callable
#######################

A bit puzzling, but after thought we found both the following do what we want 
with the __new__ argument signature.
#######################3
class Metaclass (type):
     def __init__(cls, name, bases, *args, **kwargs):
         super(Metaclass, cls).__init__(cls, name, bases, *args, **kwargs)
         print  'cls=',cls, cls.__new
         cls.__new__ = staticmethod(cls.__new)

     def __new(cls,*args):
         print 'new(',cls,args,')'
         return object.__new__(cls,*args)
     __new = staticmethod(__new)

class A:
     __metaclass__ = Metaclass
     def __init__(cls,*args):
         print '__init__(',cls,args,')'
A(3,4,5)
#######################
cls= <class '__main__.A'> <function __new at 0x008D60F0>
new( <class '__main__.A'> (3, 4, 5) )
__init__( <__main__.A object at 0x008D0C10> (3, 4, 5) )
#######################

#######################4
class Metaclass (type):
     def __init__(cls, name, bases, *args, **kwargs):
         super(Metaclass, cls).__init__(cls, name, bases, *args, **kwargs)
         print  'cls=',cls, cls.__new
         cls.__new__ = cls.__new

     def __new(cls,*args):
         print 'new(',cls,args,')'
         return object.__new__(cls,*args)
     __new = staticmethod(staticmethod(__new))

class A:
     __metaclass__ = Metaclass
     def __init__(cls,*args):
         print '__init__(',cls,args,')'

A(3,4,5)
#######################
cls= <class '__main__.A'> <staticmethod object at 0x008D0B90>
new( <class '__main__.A'> (3, 4, 5) )
__init__( <__main__.A object at 0x008D0D90> (3, 4, 5) )
#######################

This does what we want in terms of the signature, but we aren't calling the 
correct super __new__, any ideas how we can do that?
-- 
Robin Becker



More information about the Python-list mailing list