开发者

Change C object instance to Python subclass

Is it possible to change a class of a C object to a python subclass?

I am using PyGTK, and I have a ListModel that I have wrapped my own class around, but I want to turn it into a TreeModelFilter. The directions tell me to create it 开发者_JAVA技巧by doing:

class MyListStore(gtk.ListStore):
  def __init__(self, title):
    self.title = title

liststore = MyListStore(gobject.TYPE_INT, gobject.TYPE_STRING)
modelfilter = liststore.filter_new()

So I thought I could just create:

class MyFilteredListStore(gtk.TreeModelFilter):
  def __init__(self, title):
    self.title = title

But I don't know how to use filter_new to use my class, instead of gtk.TreeModelFilter.


Inheritance can be a very fluid concept in python. For starters, you should always use new style classes. To do that, make sure your classes should always inherit from "object".

It's important to note that Classes must inherit from other classes, not instances of other classes, so your example really wouldn't work there. In fact, I don't really see the difference between inheriting from X or x1.

Inheritance in python is closely tied to the "Method Resolution Order" (MRO). You can view an objects MRO using the inspect module.

>>> import inspect
>>> import pprint
>>>
>>> class X(object):
...     pass
...
>>> class Y(X):
...     pass
...
>>>
>>> pprint.pprint(inspect.getmro(Y))
(<class '__main__.Y'>, <class '__main__.X'>, <type 'object'>)
>>> 

The tuple at the end shows the order in which python will try to resolve method and attribute calls. You can modify the MRO at runtime by modifying a class's __bases__ attribute.

>>> Y.__bases__
(<class '__main__.X'>,)
>>>
>>> class Z(object):
...     pass
...
>>> Y.__bases__ = tuple([Z])
>>> pprint.pprint(inspect.getmro(Y))
(<class '__main__.Y'>, <class '__main__.Z'>, <type 'object'>)
>>>

This can get complicated if any of your classes use multiple inheritance, or if you want to preserve certain parts of the inheritance tree but not others.


The best way to handle this problem is not to subclass the TreeModel, but to assign a variable to the object that can be the ListStore or the TreeModelFilter.

class MyListStore(object):
  def __init__(self, title, filter=None):
    self.title = title
    self._model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING)
    if filter_func:
      self._model = self.model.filter_new()
      self._model.set_visible_func(filter)

I think this is the best way to get around this.

Edit

For anyone interested, I found the following to be helpful to keep from breaking old code. It acts like inheritance, without actually doing so:

  def __getattr__(self, name):
    'Get the attribute from the model if possible.'
    if hasattr(self._model, name):
      return getattr(self._model, name)
    if isinstance(self._model, gtk.TreeModelFilter):
      if hasattr(self._model.get_model(), name):
        return getattr(self._model.get_model(), name)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜