[C++-sig] .def(str(self)) compile problems

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Sun Feb 20 14:24:52 CET 2005


--- Simon Burton <simon at arrowtheory.com> wrote:

> I'm having trouble getting the __str__ wrapper for my C++ class to compile.
> Everything else i've tried works fine (methods/functions/operators), but when
> I include the  .def( str(self) )
> line the compilation fails.

I am not sure, but I don't think Boost.Python supports what you want. I am not
even sure it could support automatic conversion from std::ostream to
std::string. However, I am sure you can get what you want in simple ways. For
example:

- provide a function like this:

    std::string
    interval_as_str(interval const& self)
    {
      // conversion code here
    }

- wrap like this:

    .def("__str__", interval_as_str)

Note that the unbound C++ interval_as_str() function is wrapped as a Python
member function.

Alternatively, if interval is your own class (as opposed to a class from a
third-party library) you could define a member function interval::as_str() and
wrap in the usual way:

    .def("__str__", &interval::as_str)

There is yet another alternative that I often prefer. From a practical
viewpoint it is often the simplest alternative, but I've seen people having a
hard time getting their mind around it. I'll try to explain anyway.

First consider a pure Python example:

    class point:
    
      def __init__(self, (x,y)):
        self.xy = (x,y)
    
    p = point((1,2))
    print p

The output is:

    <__main__.point instance at 0xb73f3f4c>

Now define this unbound function:
        
    def point_as_str(self):
      return str(self.xy)
    
    print point_as_str(p)

Output:
    (1, 2)

Almost what you want, but of course "print p" would be better than "print
point_as_str(p)". Here is the trick to make it work:
   
    point.__str__ = point_as_str
    
    print p

Output:
    (1, 2)

If you come from a C++ background this Python feature may seem surprising.
However, as David Abrahams once told me, the whole secret is that "Python is a
dynamic language."

To come back to your interval class: Simply remove the def(str(self) and inject
the __str__ method from Python:

    import lift

    def interval_as_str(self):
      return list(self.upper(self), self.lower(self))

    lift.interval.__str__ = interval_as_str

Cheers,
        Ralf



		
__________________________________ 
Do you Yahoo!? 
The all-new My Yahoo! - What will yours do?
http://my.yahoo.com 



More information about the Cplusplus-sig mailing list