[C++-sig] object.attr(object& attrname) proposal.

hohe2 hohe hohehohe2 at gmail.com
Sun May 25 20:38:19 CEST 2008


Hello,

I just wonder if my current idea has already been discussed (I searched the
archive a bit but didn't find one).

Curretnly object.attr() takes only string and it finally executes
PyObject_GetAttrString() or
PyObject_SetAttrString(). Those Python C/API call takes the most time and
boost::python
overhead is relatively small. It means if we can use PyObject_GetAttr() and
PyObject_SetAttr()
with boost::python then getting/setting attribute can become much faster,
because
PyObject_*Attr() is much faster than PyObject_*AttrString().

So my proposal is:

If char const* is passed to objecjt.attr(), it uses PyObject_GetAttrStrng()
or PyObject_SetAttrStrng().
If object is passed to objecjt.attr(), it takes the object as a Python
string object and uses PyObject_GetAttr() or PyObject_SetAttr().

If attr() behaves like this, it can be useful when there are lots of objects
which you know have
the same attribute name. You can save time by first making a
boost::python::object and passing
it to every object's attr() inside a loop.

I just made a bit of modification to boost:python locally and did a quick
test, like

test 1:
  for(int i = 0; i < n; ++i)
  {
    omain.attr(attrname) = 444; //attrname is a char const*
  }

test 2:
  for(int i = 0; i < n; ++i)
  {
    object o = omain.attr(attrname); //attrname is a char const*
  }

test 3:
  for(int i = 0; i < n; ++i)
  {
    omain.attr(oaaaa) = 444; //oaaaa is boost::python::object that
represents a string
  }

test 4:
  for(int i = 0; i < n; ++i)
  {
    object o = omain.attr(oaaaa); //oaaaa is boost::python::object that
represents a string
  }

and it reasonably reflected the difference between PyObject_*Attr() and
PyObject_*AttrString.

test 1 :2783ms
test 2 :2357ms
test 3 :1882ms
test 4 :1267ms

I'd like to know your opinions about this modification.

- Koichi



p.s.
I made the modification for a test and it may be wrong (or even evil), but
I'll write it here anyway.
-----------------------------------------------------------------------------
diff -urN python/object_attributes.hpp python_p/object_attributes.hpp
--- python/object_attributes.hpp        2008-03-22 17:45:00.000000000 +0900
+++ python_p/object_attributes.hpp      2008-05-25 21:58:10.000000000 +0900
@@ -17,6 +17,7 @@
 {
     typedef char const* key_type;
     static object get(object const& target, char const* key);
+    static object get(object const& target, object const& key);
 };

 struct attribute_policies : const_attribute_policies
@@ -25,6 +26,18 @@
     static void del(object const&target, char const* key);
 };

+struct const_objattribute_policies
+{
+    typedef object const key_type;
+    static object get(object const& target, object const& key);
+};
+
+struct objattribute_policies : const_objattribute_policies
+{
+    static object const& set(object const& target, object const& key,
object const& value);
+    static void del(object const&target, object const& key);
+};
+
 //
 // implementation
 //
@@ -42,11 +55,30 @@
     return const_object_attribute(x, name);
 }

+template <class U>
+inline object_objattribute object_operators<U>::attr(object const& name)
+{
+    object_cref2 x = *static_cast<U*>(this);
+    return object_objattribute(x, name);
+}
+
+template <class U>
+inline const_object_objattribute object_operators<U>::attr(object const&
name) const
+{
+    object_cref2 x = *static_cast<U const*>(this);
+    return const_object_objattribute(x, name);
+}
+
 inline object const_attribute_policies::get(object const& target, char
const* key)
 {
     return python::getattr(target, key);
 }

+inline object const_objattribute_policies::get(object const& target, object
const& key)
+{
+    return python::getattr(target, key);
+}
+
 inline object const& attribute_policies::set(
     object const& target
     , char const* key
@@ -56,6 +88,15 @@
     return value;
 }

+inline object const& objattribute_policies::set(
+    object const& target
+    , object const& key
+    , object const& value)
+{
+    python::setattr(target, key, value);
+    return value;
+}
+
 inline void attribute_policies::del(
     object const& target
     , char const* key)
@@ -63,6 +104,13 @@
     python::delattr(target, key);
 }

+inline void objattribute_policies::del(
+    object const& target
+    , object const& key)
+{
+    python::delattr(target, key);
+}
+
 }}} // namespace boost::python::api

 #endif // OBJECT_ATTRIBUTES_DWA2002615_HPP
diff -urN python/object_core.hpp python_p/object_core.hpp
--- python/object_core.hpp      2008-03-22 17:45:00.000000000 +0900
+++ python_p/object_core.hpp    2008-05-25 21:58:36.000000000 +0900
@@ -59,6 +59,8 @@

   struct const_attribute_policies;
   struct attribute_policies;
+  struct const_objattribute_policies;
+  struct objattribute_policies;
   struct const_item_policies;
   struct item_policies;
   struct const_slice_policies;
@@ -67,6 +69,8 @@

   typedef proxy<const_attribute_policies> const_object_attribute;
   typedef proxy<attribute_policies> object_attribute;
+  typedef proxy<const_objattribute_policies> const_object_objattribute;
+  typedef proxy<objattribute_policies> object_objattribute;
   typedef proxy<const_item_policies> const_object_item;
   typedef proxy<item_policies> object_item;
   typedef proxy<const_slice_policies> const_object_slice;
@@ -108,6 +112,8 @@
       //
       const_object_attribute attr(char const*) const;
       object_attribute attr(char const*);
+      const_object_objattribute attr(object const&) const;
+      object_objattribute attr(object const&);

       // item access
       //
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080526/86a53f8e/attachment.htm>


More information about the Cplusplus-sig mailing list