0

I ran into some strange errors and just ask myself if I have a fundamental issue in my class hierarchy. I am an absolute newbie if it comes to python. So if this approach appears llike total crap - you know why that is :-)

I have a couple of classes in an application I designed around the MVC pattern. The applications controller has control over four objects I call 'devices', since they act like independant devices. Each device runs actions (computations), image processing in this case. Those actions are meant to run inside separate threads. So each device should open an 'own' thread and have its computation done in that thread.

For this I designed a base class describing a 'device', so all devices inherit their basic setup and logic, especially the way they are controlled by the controller. For the threads I implemented a 'worker' class, I plan to push that classes instances into the threads. That part is not working yet. Those worker classes are designed like this: The base device class contains a nested worker base class. It also implements some basic control methods to handle a worker instance that is stored as a member of the base device class. All specialized device classes (derived from the base device class) also implement a nested worker class. Those classes are derived from the base worker class nested inside the base device class. Here is a sketch of the hierarchy:

/class Device/
             /methods
             /members
             /class Worker/
                          /methods
                          /members
/class fooDevice(Device)/
                        /methods
                        /members
                        /class fooWorker(Device.Worker)/
                                                       /methods
                                                       /members
/class barDevice(Device)/
                        /methods
                        /members
                        /class barWorker(Device.Worker)/
                                                       /methods
                                                       /members

Note that the classes fooWorker and barWorker are both derived from Device.Worker!

My question is: although the stuff appears to work during setup I get runtime errors. not sure yet where they come from, what they mean. But first I want to understand of that class hierarchy layout I made up does make sense at all? Is it totally twisted nonsense? Or in common use?

Thanks!

arkascha
  • 41,620
  • 7
  • 58
  • 90
  • 2
    While you can nest class definitions in Python, it doesn't really provide m(any) benefits except complicate accessing them. – martineau Jan 29 '13 at 10:53
  • A class hierarchy is defined by the class' inheritance relation, not by nesting them. Unless you have extremely special use case, don't nest class definitions. If you are looking for an equivalent for name spaces, use modules and packages. – Ber Jan 29 '13 at 10:57
  • Ok thanks, I already split that application into a few modules, that really helps in housekeeping. The nesting came natural to me, since the workers are something internal to devices. But you are both right: I cannot see any technical advantage of that design. Probably I should 'free' the worker classes and reference them by unique names instead. – arkascha Jan 29 '13 at 11:05
  • The answers to the question [Python nested classes scope](http://stackoverflow.com/q/1765677/355230) might be of interest to you. – martineau Jan 29 '13 at 14:40
  • @martineau Thanks, but I don't see anything new in those answers. Note that I have no problems with the nesting, that works fine. My question was, if that is an approach that makes sense. – arkascha Jan 29 '13 at 16:04
  • @arkascha: I thought the question was relevant because most of the answers seemed to be saying that the nesting of classes should generally be avoided in Python (and why, as well as how, to achieve the similar results in some cases). – martineau Jan 29 '13 at 16:12
  • @martineau Sure, I read that many times. However the typical reason given is that accessing instanciations of nested classes are harder to refer to. I don't really see that issue, the references are logical and not complex. I was unsure of the inheritance across nesting levels as sketched works and makes sense. Actually I got things to work. The issue was totally unrelated to the inheritance structure. – arkascha Jan 29 '13 at 23:39
  • @arkascha: Yes, while its seems (and is) very logical, and certainly works, in Python, the inner class doesn't have special access to the outer class's scope or gets anything else from it -- so to most folks, just providing a namespace isn't worth the trouble and might even lead some to believe -- wrongly -- there was a dependency of some sort between the two. – martineau Jan 30 '13 at 01:10

1 Answers1

1

Nested classes can make sense. Django uses them for Meta configuration in models and forms. I use them sometimes in factory patterns, e.g.

   class BaseFactory(object):
      class FactoryItem(object):
          pass 

      @classmethod
      def create(cls):
          return cls.FactoryItem()

   class ShoeFactory(BaseFactory):
      class FactoryItem(BaseFactory.FactoryItem):
          def laces(self):
              return 1

But you can just as easy define the FactoryItem classes globally and assign them to "FactoryItem" class member, e.g.

class Shoe(BaseFactory.FactoryItem):
    ...

class ShoeFactory(BaseFactory):
    FactoryItem = Shoe

The only issue I've ran into is deserialization of objects. I can't really remember when/where/why, probably pickle was being used somewhere and it failed to resolve a nested class.

What specific runtime issues are you experiencing?

  • `RuntimeError: '__init__' method of object's base class (Worker) not called.` It is raised the moment I call `self.worker.moveToThread(self.thread)`, so an attempt to move a QThread instance into a thread (I use the pySide Qt bindings). This is somewhat funny, since my debug output clearly proves that for each worker object instanciated both `init` functions are called: for the worker class itself and for the base worker class. I _thought_ the problem might be cause by the nesting of classes. Actually I read a few things about pickle now and think it is worth following that feeling... – arkascha Jan 29 '13 at 11:37