0

I have a class (PlayerList) that contains Player objects (or subclasses) by inheriting from list builtin. I want each of the Player objects to use the container's attribute true_dice. The problem is that for testing purposes I need each of the players to have the ability to use their own as well, if they are not part of a PlayerList

class PlayerList(list):
    def __init__(plist):
        # plist is a list of Player objects
        self.true_dice = [0,0,0,0]
        super().__init__(plist)

class Player:
    def __init__():
        self.true_dice = "<Magical code that gets containers true_dice>"
    
    def turn(self):
        "..."
        self.true_dice[2] = 1 # Modify true_dice should modify PlayerList's aswell

What is the pythonic way to achieve this? A google search turns up no results.

I was thinking perhaps overriding __getattribute__ would work, but then I would have to store a reference to the PlayerList in the class, and that is a very tightly coupled solution:

class Player:
...
    def __getattribute__(self, attrname):
            if attrname=="true_dice":
                return player_list_reference.true_dice # Defined in __init__
            else:
                return self.__dict__[attrname]

Or perhaps I could run an update function every time a member of the 'PlayerList' changes its true_dice attribute. This would separate concerns rather well...

Please comment any and all requests for edits.

10
  • Can you please provide a minimal reproducible example? Is your issue defining the attribute access on Player, using the PlayerList attribute, or falling back to (or preferring?) the Player's own attribute? Commented Apr 26, 2022 at 15:29
  • A bit of both I think... I'm on it. Commented Apr 26, 2022 at 15:29
  • What is player_list_reference? Is this some global attribute, a placeholder for something to be defined, or a mistyped attribute of Player? Commented Apr 26, 2022 at 15:30
  • 1
    If it is for testing purposes, use unittest and mock the attribute or use some other testing framework. Commented Apr 26, 2022 at 15:37
  • @MisterMiyagi Like I said "but then I would have to store a reference to the PlayerList in the class, and that is a very tightly coupled solution" It is a reference to the container that it is a part of. Commented Apr 26, 2022 at 15:45

1 Answer 1

0

All credit to @MisterMiyagi, suggested this answer.

He advocated for something like this if I understand correctly.

class PlayerList(list):
    def __init__(self, plist):
        # plist is a list of Player objects
        self.true_dice = [False, False, False, False]
        for player in plist:
            player.true_dice = self.true_dice # Set true_dice of members
        super().__init__(plist)

class Player:
    def __init__(self, true_dice=None):
        self.true_dice = true_dice
    def turn(self):
        "..."
        self.true_dice[2] = 1 # Modify true_dice should modify PlayerList's aswell

# Implementation Change, not sure how to make this automatic...
pl = PlayerList([Player()])
Sign up to request clarification or add additional context in comments.

Comments

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.