0

I tried to create a data structure in python, where I have an outerClass, innerClass, both would include several variables and the outerClass has a list, storing objects of innerClass instances.

I managed to create the outerClass instances but failed to do it with innerClass instances, especially unable to append them to my innerInstancesList.

I'm quite new to python, not sure exactly if this is the best way implement this structure. Trying to make something similar:

Outerinstance1
    variable1
    variable2
    Innerinstance1
        variable1
        variable2
    Innerinstance2
        variable1
        variable2 
    Innerinstance3
        variable1
Outerinstance2
    variable1

Is there a better way to implement this in python? My sample code:

 class outerClass:
    def __init__(self, name):
        self.name = name
        self.innerInstancesList= []
        self.innerClass = self.innerClass()
        
    class innerClass:
        def __init__(self):
            self.id = 0
            self.c = "char"
        def init2(self, id, c):
            self.id = id
            self.c = c

outerInstance = outerClass("Outerinstance1")
print (hex(id(outerInstance)))

for a in range(0,5):
    outerInstance.innerClass.init2(1, a)
    x = outerInstance.innerClass
    print (hex(id(x)))
    outerInstance.innerInstancesList.append(x)
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
d4m
  • 3
  • 2
  • 1
    It's worth pointing out you seem to have confusion between `innerClass`, which is the class itself, and `innerClass()`, which returns a new instance of that class. – CrazyChucky Oct 24 '21 at 18:39
  • 1
    before looking for new implementation, did you check if your program produces the right output? all the instances in `innerInstancesList` point to the same object... if you look at `outerInstance.innerInstancesList[2].c` will be same as for `3` and so on (equal to the last appended) – cards Oct 24 '21 at 18:39
  • I know it don't work fine, that is why I'm looking for a solution I can implement. – d4m Oct 24 '21 at 19:28

2 Answers2

0

It appears that ultimately, you want instances of one class to each track multiple instances of another class. This doesn't actually require that one class be defined inside the other. Let's call them Group and Member; each Group instance can hold multiple instances of Member. A straightforward way to declare and demonstrate such a relationship would look like so:

class Group:
    def __init__(self, name):
        self.name = name
        self.members = []

    def __repr__(self):
        return f'Group(name={self.name}, members={self.members})'
        
class Member:
    def __init__(self, id, char):
        self.id = id
        self.char = char

    def __repr__(self):
        return f'Member(id={self.id}, char={self.char})'


group = Group('Test Group')
print(group)

for a in range(5):
    member = Member(a, chr(a + 97))
    print(member)
    group.members.append(member)

print(group)

I've added __repr__ methods (using f-strings) so that it's easy to tell what objects are which when printed. As you can see, both classes are defined at the top (module) level, then multiple instances of Member are appended to the members list of the Group instance.

This outputs:

Group(name='Test Group', members=[])
Member(id=0, c='a')
Member(id=1, c='b')
Member(id=2, c='c')
Member(id=3, c='d')
Member(id=4, c='e')
Group(name='Test Group', members=[Member(id=0, c='a'), Member(id=1, c='b'), Member(id=2, c='c'), Member(id=3, c='d'), Member(id=4, c='e')])

You could avoid some boilerplate in your class definitions (at least in this simple example) by using dataclasses. They're a handy way to simplify declarations of classes that mostly just store some data fields like this, because they can automatically generate __init__ and __repr__ methods for you, among other things.

from dataclasses import dataclass, field

@dataclass
class Group:
    name: str
    members: list = field(init=False, default_factory=list)

@dataclass        
class Member:
    id: int
    char: str


# Rest of the code unchanged; will generate the same output
CrazyChucky
  • 3,263
  • 4
  • 11
  • 25
-1

I don't think there is. I think you might be better without inner classes, does not seem to be a great reason to use one. You could just add the class to the constructor, append it, and list it that way.

jshwi
  • 84
  • 1
  • 1
  • 9