2

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 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.

7
  • @agf is that a better title? It's more about the parent/child of general Python, but the PyGTK is just to give an example. Commented Sep 28, 2011 at 21:44
  • stackoverflow.com/questions/2153295/python-object-conversion This question is close, but I may want to use the init in my own program. I haven't decided. Commented Sep 28, 2011 at 21:55
  • 2
    What is it you're asking? How to take a class instance that exists, and change it into an instance of a subclass of its class? Or how to get a method to return a different type than it's written to? The answer to the first is "switch the __class__" and the answer to the second is "rewrite the method". Whatever it is, your current title isn't much better than the old one; maybe you mean "Create class instance from subclass of it's usual parent class" or something like that? Commented Sep 28, 2011 at 21:55
  • Nevermind to question 2153295. I can't assign to class, as the object is defined in C. Commented Sep 28, 2011 at 22:05
  • How do I handle a question if there's not an answer (I can't answer it myself either)? I think I may just take another route to solve my problem. Do I delete the question, or just choose the best available? Commented Sep 29, 2011 at 19:16

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Well, the Python programmers don't have a way to directly create a TreeModelFilter, so instead, I'm wanting to turn the instance from one object to a subclass of the object. I can't change class unfortunately.
@bradlis7 : if you have problems with TreeModelFilter, open a new question showing the code snippet you try to run, and we will have a serious look at it !
1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.