0

I am obviously missing something fundamental here. Hopefully someone can put me right! TIA

I have an array of objects whose class contains instances of another object. But when I set a property for one of these then they all change.

class direction():
    dest = -1
    lock = ''
class room():
    roomname = ''
    desc = ''
    n = direction()
    s = direction()
    w = direction()
    e = direction()
    item = ''

rooms = []
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )

rooms[0].roomname = 'outside'
rooms[0].desc = ''
rooms[0].n.dest = 4
rooms[0].item = ''

rooms[1].roomname = 'hall'
rooms[1].desc = 'The hallway has doors to the east and south'
rooms[1].n.dest = 2
rooms[1].item = ''

if I iterate through the n.dest properties in the rooms list then all are returned as 2

It is as if the direction objects in each object in the rooms list are all a single instance and setting one value in one of them sets it for all of them.

2
  • BTW please ignore the lack of constructors - I am keeping the code simple just now and will add them later. Commented Apr 30, 2019 at 12:42
  • 1
    The lack of constructors is the problem. Commented Apr 30, 2019 at 12:59

3 Answers 3

1

Your attributes are all declared at class level, not instance level, meaning that every instance of the class will share the same values. I think you want:

class Room():
    def __init__(self):
        self.roomname = ''
        self.desc = ''
        self.n = direction()
        self.s = direction()
        self.w = direction()
        self.e = direction()
        self.item = ''
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you, that works - but I have no idea why. I will now look up the difference between class and instance level...
digitalocean.com/community/tutorials/… I understand now. Thank you.
BUT what I don't now understand is WHY do my rooms all retain different roomname properties etc and it is only the nested class which is affected?
When you do rooms[1].roomname = 'hall you create a new instance attribute that will shadow the class atrribute. With rooms[1].n.dest = 2 you set a new value for the attribute dest, but this attribute belongs to an existing class level attribute n.
1

You're missing constructors, and therefore missing instance variables

You're defining class variables, so each variable is the same between all instances

Comments

0

In each class, you have declared a bunch of class attributes. An assignment like rooms[0].roomname = 'outside' creates an instance attribute that shadows room.roomname. However, you never actually make any such assignment to rooms[0].n, so each assignment to something like rooms[0].n.dest is adding an instance attribute dest to the same instance of direction shared by each instance of room.

In your attempt to "simplify" your code, you've made it more complicated. Define __init__ to set your instance attributes; class attributes are not used as often.

class Direction:
    def __init__(self, dest, lock=''):
        self.dest = dest
        self.lock = lock

class Room:
    def __init__(self, roomname, desc, item=''):
        self.roomname = roomname
        self.desc = desc
        self.n = direction()
        self.s = direction()
        self.w = direction()
        self.e = direction()
        self.item = item


rooms = []
r = Room('outside', '')
r.n.dest = 4
rooms.append(r)


r = Room('hall', 'The hallway has doors to the east and south')
r.n.dest = 2
rooms.append(r)

1 Comment

Thank you that makes sense now. I've just had a crash course on class and instance attributes!

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.