Skip to content
Advertisement

Python: Inner Class

I am trying to create a json string from a class and I defined my class as follows:

import json
import ast
from datetime import datetime
import pytz
import time

class OuterClass:
    def __init__(self):
        self.Header = None
        self.Body = None

    class Header:
        def __init__(self, ID = None, Name = None):
            self.ID =  ID
            self.Name = Name 

    class Body:
        def __init__(self, DateTime=None, Display=None):
            self.DateTime = DateTime
            self.Display = Display

def current_time_by_timezone(timezone_input):
    return datetime.now(pytz.timezone(timezone_input))

if __name__ == '__main__':
    response = OuterClass()
    header = response.Header('123', 'Some Name')
    body = response.Body(current_time_by_timezone('US/Central'), 'NOT VALID')
    print(json.dumps(response.__dict__))

I’m getting an error ‘TypeError: ‘NoneType’ object is not callable’. Is it because I’m setting the Header and Body in the OuterClass definition myself to None?

Advertisement

Answer

The problem with your code is these lines:

    self.Header = None
    self.Body = None

These create instance variables named Header and Body on every instance of OuterClass, so you can never access the class variables (the nested classes) via an instance, only via OuterClass itself.

It’s not very clear what your intention is with this data structure. Defining a class inside another class doesn’t do anything special in Python (by default, you could probably make there be special behavior with special effort, like using a metaclass that makes the inner classes into descriptors). Generally though, there’s no implied relationship between the classes.

If you want your OuterClass to create instances of the other two classes, you can do that without nesting their definitions. Just put the class definitions at top level and write a method that creates an instance at an appropriate time and does something useful with it (like binding it to an instance variable).

You might want something like:

def Header:
   ...

def Response:
   def __init__(self):
       self.header = None

   def make_header(self, *args):
       self.header = Header(*args)
       return self.header

You could keep the classes nested as long as you don’t expect that to mean anything special, just be sure that you don’t use the class name as an instance variable, or you’ll shadow the name of the nested class (a capitalization difference, like self.header vs self.Header could be enough).

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement