Is there a way to instantiate a subclass from a class constructor?

Stefan Schwarzer s.schwarzer at ndh.net
Sun Sep 23 11:39:58 EDT 2001


Hello Paul

Paul Rubin wrote:
> > A factory function like this is a standard solution that has been
> > discussed in several posts on this list.  Don't knock it.
> 
> I'm not knocking it, I just don't see how to extend the class from
> additional base classes without having to add more special code to
> the factory function, which is against the OO spirit.  Any thoughts?

I would use the factory funtion approach:

# polygon_test
class Polygon:
    def identify(self):
        print self.__class__
    
class Triangle(Polygon):
    def triangle_method(self):
        pass

class Rectangle(Polygon):
    def rectangle_method(self):
        pass

def factory(sides=None):
    special_polygons = {3: Triangle,
                        4: Rectangle}
    if sides in special_polygons.keys():
        return special_polygons[sides]()
    else:
        return Polygon()

Python 2.1.1 (#0, Aug  5 2001, 15:48:16) [EMX GCC 2.8.1] on os2emx
Type "copyright", "credits" or "license" for more information.
>>> import polygon_test
>>> p = polygon_test.factory()
>>> p.identify()
polygon_test.Polygon
>>> t = polygon_test.factory(3)
>>> t.identify()
polygon_test.Triangle
>>> t.triangle_method()
>>>

> The obvious workaround is to define a function that calls the appropriate
> constructor, e.g.
>   def newpoly(sides):
>     if sides==3: return Triangle(...)
>     ...
> but this isn't so great, because it doesn't fit in with multiple base
> classes:
>    class RotatingMixin:
>      def rotate(): ...    # make object rotate on the screen
> 
>    class RotatingPolygon(Polygon, RotatingMixin): pass
> 
> Ideally I'd like a definition like that to automatically result in
> rotating triangles and rectangles as well as polygons.  I think CLOS

Your first model,

>    class Polygon:
>      def __init__(sides=None):
>         if sides==3: return Triangle(...)

wouldn't do that either, even if

> but of course class initializers in Python don't return values.

would not be true. You would have:

         Polygon
        /    |   \
Triangle     |    RotatingPolygon
             |
          Rectangle

so Triangle and Rectangle wouldn't inherit the rotate method. However, you
could add the rotate method directly to the Polygon class. (Chuck Esterbrook
has written an article about this in Linux Journal, if I remember correctly.)
And in that case, the factory function would also do the job.

Stefan



More information about the Python-list mailing list