Visitor pattern in python

bogdan picture bogdan · Sep 17, 2014 · Viewed 12.2k times · Source

here is a simplified implementation of the visitor pattern in C++. Ist it possible to implement something like this in Python?

I need it, because I will pass Objects from C++ code to a function in Python. My idea was to implement a visitor in Python to find out the type of the Object.

My C++ code:

#include <iostream>
#include <string>


class t_element_base
{
public:
    virtual void accept( class t_visitor &v ) = 0;
};


class t_element_deriv_one: public t_element_base
{
public:
    void accept( t_visitor &v );

    std::string t_element_deriv_one_text()
    {
        return "t_element_deriv_one";
    }
};


class t_element_deriv_two: public t_element_base
{
public:
    void accept( t_visitor &v );

    std::string t_element_deriv_two_text()
    {
        return "t_element_deriv_one";
    }
};


class t_visitor
{
public:
    void visit( t_element_deriv_one& e ){ std::cout << e.t_element_deriv_one_text() << std::endl; }
    void visit( t_element_deriv_two& e ){ std::cout << e.t_element_deriv_two_text() << std::endl; }
};


void t_element_deriv_one::accept( t_visitor &v )
{
    v.visit( *this );
}

void t_element_deriv_two::accept( t_visitor &v )
{
    v.visit( *this );
}


int
main
(
void
)
{
    t_element_base* list[] =
    {
        new t_element_deriv_one(), new t_element_deriv_two()
    };
    t_visitor visitor;

    for( int i = 0; i < 2; i++ )
        list[ i ]->accept( visitor );
}

Answer

Tony Suffolk 66 picture Tony Suffolk 66 · Sep 17, 2014

The visitor pattern can be implemented in Python, I use it to implement a clean interface between my data and presentation layer. The data layer can determine the ordering of the data. and the presentation layer simply prints/formats it :

In my data module I have :

 class visited(object):
     ....
     def accept(self, visitor):
         visitor.visit(self)
         for child in self.children():
             child.accept(visitor)

 class typeA(visited):
    ....

All of my data classes inherit from this visited class, and the visited class also exposes some simple functions for basic data all my objects need e.g. name, parent, etc, and methods for managing the child list - which is exposed by the children() method used above. each of the sub class will build their own data, have their own properties and maybe even their own child class - which get added to the children list maintain by the visited super class.

My visitor class is like this :

class visitor(object):
      def __init__(self, obj_id):
          data_obj = _find_data_instance( obj_id )
          data_obj.accept(self)

      def visit( self, data_obj):
          if isinstance(data_obj, typeA):
               self.visit_typeA( dataobj)

      def visit_typeA(self, dataobj):
          """Formats the data for typeA"""
          ...

the _find_data_instance is some code that builds or finds a instance of one of my data instances. In my case all of my data classes have a constructor which takes a objectId and return, and the visitor object knows what data class to use.