-1

I'm trying to append inner class instances into a list which is defined as an attribute of the outer class instances. However I get an "AttributeError: type object 'Outer' has no attribute 'Inner_list'". Here's the code:

import matplotlib.pyplot as plt
import numpy as np


#Create new outer class
class Outer():

    def __init__(self, name = "", n_users = 1):
        self.user_name = name
        self.num_users = n_users
        self.Inner_list = []

#Create new inner class 
    class Inner():

        def __init__(self, n = 1, P = 0, w = 1, t = 0):
            self.number = n
            self.power = P
            self.num_windows = w
            self.func_time = t

        def windows(self, w1 = np.array([0,0]), w2 = np.array([0,0])):    
            self.window_1 = w1
            self.window_2 = w2
            self.daily_hours = np.zeros(1440)
            self.daily_hours[w1[0]:(w1[1])]=np.ones(np.diff(w1))
            self.daily_hours[w2[0]:(w2[1])]=np.ones(np.diff(w2))
            Outer.Inner_list.append(self)

#Create new instance of outer class
Out_instance_1 = Outer("outer",300)

#Create new instance of inner class
Inn_instance_1 = Out_instance_1.Inner(5,7,2,5)
Inn_instance_1.windows([6*60,8*60],[18*60,23*60])

Python says that Outer object has no attribute "Inner_list", and that's true because I understand that "Inner_list" is an attribute of Outer instances and not of the Outer object. If i create an Outer_instance and type "Outer_instance.App_list" it shows an empty list, as I want. So the problem here is that I am not able to make the code append the Inner instances to the generic Outer instance within which it is defined. Any help will be much appreciated, thanks

  • Possible duplicate of [Nested classes' scope?](https://stackoverflow.com/questions/1765677/nested-classes-scope) – Silvio Mayolo Nov 28 '17 at 14:53
  • There is no such a "generic Outer instance ". `Out_instance_1.Inner`, `Out_instance_2.Inner`, `Outer.Inner` all refer to the same class, there is no difference. That said, flat is better than nested. Whatever problem you are triying to solve there are probably better ways. – Stop harming Monica Nov 28 '17 at 15:06
  • Thanks for the reply. I am sure there can be also better ways, that's why I am asking. Anyway, yes, if I manually create (in the console) a new Outer instance and type "New_Outer_Instance.Appl_list" it shows me correctly the empty list that I want. But the problem is that if I try to do that with the script it doesn't work, because I don't know in advance the name of the "New_Outer_Instance", I just know that it will be an instance of the Outer class, and I thought that this code would make Python understand it but it doesn't. Any ideas? – Franz Eskö Nov 28 '17 at 16:55
  • @FrancescoLombardi There is nothing for python to understand, neither `Inner` nor their instances are related to any particular instance of `Outer` so you cannot expect python to magically find one. They do not even need any instances of `Outer`to exist. Idea: try to solve the problem without nesting the classes, it is doing nothing but confusing you. For more ideas look at the answer by @AndreyF where an instance of `Outer` is explicitly attached to each instance of `Inner`. – Stop harming Monica Nov 28 '17 at 22:21
  • The idea by @AndreyF worked perfectly, but still keeping the indentation of the inner class, otherwise it won't work. Why do you say that it is better to have not nested classes? – Franz Eskö Nov 29 '17 at 15:15

1 Answers1

0

I'm not sure this is good programming but you can pass the outer class instance to the inner class instance and then accessing it from the inner class a field:

class Outer():

    def __init__(self, name = "", n_users = 1):
        self.user_name = name
        self.num_users = n_users
        self.Inner_list = []

#Create new inner class
    class Inner():

        def __init__(self, outer, n = 1, P = 0, w = 1, t = 0): # added outer to the constructor
            self.number = n
            self.power = P
            self.num_windows = w
            self.func_time = t
            self.outer = outer # added an 'outer' field

        def windows(self, w1 = np.array([0,0]), w2 = np.array([0,0])):
            self.window_1 = w1
            self.window_2 = w2
            self.daily_hours = np.zeros(1440)
            self.daily_hours[w1[0]:(w1[1])]=np.ones(np.diff(w1))
            self.daily_hours[w2[0]:(w2[1])]=np.ones(np.diff(w2))
            self.outer.Inner_list.append(self) # accessing outer object as a field

#Create new instance of outer class
Out_instance_1 = Outer("outer",300)

#Create new instance of inner class
Inn_instance_1 = Out_instance_1.Inner(Out_instance_1, 5,7,2,5) # pass the outer object to the inner object
Inn_instance_1.windows([6*60,8*60],[18*60,23*60]) 
AndreyF
  • 1,798
  • 1
  • 14
  • 25