Class factory functions

Peter Otten __peter__ at web.de
Sun Mar 25 05:58:00 EDT 2007


Steven D'Aprano wrote:

> Here's a simple class-factory function that returns a sub-class of the
> old-style class it is passed.
> 
> def verbosify_oclass(klass):
> """Returns a verbose sub-class of old-style klass."""
> class VClass(klass):
> def __init__(self, *args, **kwargs):
> print "Calling initializer __init__ ..."
> klass.__init__(self, *args, **kwargs)
> return VClass
> 
> 
> Here it is in action:
> 
>>>> class Parrot:
> ...     def __init__(self, colour): self.colour = colour
> ...
>>>> VParrot = verbosify_oclass(Parrot)
>>>> bird = VParrot('red')
> Calling initializer __init__ ...
>>>> bird.colour
> 'red'
> 
> 
> Here's an equivalent for new-style classes. It uses super() because I
> understand that super() is preferred to calling the super-class by name.
> 
> 
> def verbosify_nclass(klass):
>     """Returns a verbose sub-class of new-style klass."""
>     class VClass(klass):
>         def __new__(cls, *args, **kwargs):
>             print "Calling constructor __new__ ..."
>             return super(klass, cls).__new__(cls, *args, **kwargs)
>         def __init__(self, *args, **kwargs):
>             print "Calling initializer __init__ ..."
>             super(klass, self).__init__(*args, **kwargs)
>     return VClass
> 
> 
> 
> But it doesn't work:
> 
>>>> vint = verbosify_nclass(int)
>>>> vint(42)
> Calling constructor __new__ ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<stdin>", line 6, in __new__
> TypeError: object.__new__(VClass) is not safe, use int.__new__()
> 
> 
> What am I doing wrong?

Why would you skip VClass in the super() calls? This should work:

def verbosify_nclass(klass):
    """Returns a verbose sub-class of new-style klass."""
    class VClass(klass):
        def __new__(cls, *args, **kwargs):
            print "Calling constructor __new__ ..."
            return super(VClass, cls).__new__(cls, *args, **kwargs)
        def __init__(self, *args, **kwargs):
            print "Calling initializer __init__ ..."
            super(VClass, self).__init__(*args, **kwargs)
    return VClass

Peer



More information about the Python-list mailing list