Class factory functions

S

Steven D'Aprano

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:
.... def __init__(self, colour): self.colour = 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:
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?


Here's one solution: dump the call to super() and call the super-class
directly. It seems to work. Are there any problems in not using super()?
What about multiple inheritance?


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

Peter Otten

Steven said:
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:

... def __init__(self, colour): self.colour = 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:

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top