0

I want to make a class where one object in that class belongs to a different type of class (though not in a nested way), and the second class object can point back to the class object that contains it.

That's pretty abstract. Like, let's say I want a class called "Party", which contains objects of the class Character. Let's say that Party has an int object called Total_gold. I know I could create that using something like:

class Party(object):
    def __init__(self, G1, c1, c2, ...other_stuff_goes_here):
        self.Total_gold = G1;
        self.char1 = Character(c1);
        self.char2 = Character(c2);
        # more stuff to initiate Party

class Character(object):
    def __init__(self, other_stuff_goes_here):
        # stuff to initiate Character

Now, let's say I have a function that takes in a Character object, but I want it to alter the Party that contains that Character. For example, let's say I want to have a function, Spend, that decreases the Party's Total_gold. Is there a way for Spend to take in a Character object, and then access the Party the Character is in?
Something like:

def Spend(character, amount): 
    #reduces the Total_gold of the party the character belongs to.
    character.Party.Total_gold -= amount

If so, how would I do this? I assume I need to put something in the __init__ function, but I don't know how I would do that. Python doesn't have pointers, right?

If another post has covered this, please let me know. I wasn't sure how to even ask this.

Thank you.

3
  • 1
    One option is to make each character store their own gold. Then make Party.Total_gold a @property that sums all the characters' gold. Commented Jan 5, 2021 at 4:33
  • From OO perspective this is a violation of Dependency Inversion Principle (DIP). Making a class Character associate to another class Party (because a Party has Character) is a violation of DIP Commented Jan 5, 2021 at 5:01
  • I like your idea about using @property; I didn't know those existed, this taught me something useful. Thank you. But, let's say I also needed a way to check if amount was less than Party.Total_gold (so that a Character can spend more gold than it has, but cannot spend more gold than the Party has). That's not possible to do with @property, right? Commented Jan 6, 2021 at 14:31

1 Answer 1

1

Python objects don't internally store any information about being a member of another object, so you'll need to store the instance of Party inside of both Characters. The simplest way to do this is to pass self to Character.__init__:

class Character:
    def __init__(self, party, other_arg):
        self.party = party
        # Other stuff goes here

class Party:
    def __init__(self, c1, ...):
    self.char = Character(self, c1)

Then:

def spend(character, amount):
    character.party.total_gold -= amount
Sign up to request clarification or add additional context in comments.

4 Comments

Please delete this. This is 100% incorrect design. Either A has B or B has A but both is not a good design.
My answer achieves exactly what the question is asking. Having circular references is a sign of bad design, but the implementation itself doesn't matter. If I were OP I'd redesign my program so that an object doesn't need to know what contains it (that makes no sense) but that's not my concern so I don't see any reason to delete my answer.
First, thank you for the answer. Second, is there a short way to explain what a circular reference is bad design? I was a computer science major briefly, but much of my coding is self-taught, and I don't think I ever learned why the DIP is so important. Thank you.
@Simon one good reason is that circular references will never be garbage collected. But, on a bigger scale, it's good to structure objects in a way that represents data: when a container has a member object, the member represents some data that the container uses for its own purposes. It's usually a sign of bad engineering if containers and members need to know about each other: you could, for example, instead pass some sort of "global state" object around, or move some functionality to the container.

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.