[C++-sig] how to override __setattr__ of an extension class

Jim Bosch talljimbo at gmail.com
Sat Feb 25 04:19:59 CET 2012


On 02/23/2012 12:04 PM, Holger Joukl wrote:
>
> Hi,
>
> I'm trying to instrument a wrapped class with  custom __setattr__
> mechanics:
>
>          .def("__setattr__",&MyExtensionClass::setattr)
>
> How can I call the base class __setattr__ from within setattr and not run
> into infinite recursion?
>
> I.e. the analogon in C++ to
>
>>> class Foo(object):
> ...     def __setattr__(self, attr, value):
> ...         print "custom __setattr__"
> ...         object.__setattr__(self, attr, value)
> ...
>>>> foo = Foo()
>>>> foo.x = 23
> custom __setattr__
>>>> foo.x
> 23
>>>>
>
> To actually write to my instance dict I currently do
>
>      PyObject* __dict__ = PyObject_GetAttrString(m_self, const_cast<char*>
> ("__dict__"));
>      PyDict_SetItemString(__dict__, name, value.ptr());
>
> inside MyExtensionClass::setattr (where m_self is PyObj*)
>
> Is there a better way?
>

Everything I can think of (e.g. extract the base class from __bases__[0] 
and call its setattr) is functionally equivalent and not any prettier.


> On a sidenote, I initially thought I could wrap the __dict__ in bp::dict()
> to
> use its nice Python-like API for item assignment but this seems to always
> make a copy of the __dict__.
> I.e something like
>
> bp::dict bp_dict(__dict__);
> bp_dict[name] = value;
>
> won't work.
>

The trick is to do:

bp::dict bp_dict = bp::extract<bp::dict>(__dict__);
bp_dict[name] = value;

Just calling the bp::dict invokes Python's dict constructor, which does 
a copy.


Jim


More information about the Cplusplus-sig mailing list