23-08-2009 Kreso <kkumernott...@thatfamoussearchenginesmail.com> wrote:

I would like to create a list-like container class so that, additionally
to usual list methods, I could attach attributes to the container instances.
However, I would like it so that the items contained in the particular
instance of container somehow 'inherit' those attributes i.e.

cont = Container()
cont.color = 'blue'
cont.append(item)
print item.color
'blue'

[snip]

class Player:
    """Class for items"""

    def __init__(self, playerdata, team):
        self.data = playerdata
        for key in team.__dict__:
            setattr(self, key, team.__dict__[key])
        return


class Team(list):
    """Class for containers"""
   def __init__(self, teamdata, playerdata):
        for key in teamdata:
            setattr(self, key, teamdata[key])
        for item in playerdata:
            self.append(Player(item, self))
        return

lakersdata = {'name' : 'Lakers', 'kitcolor' : 'yellow'}
lakersplayers = [['Kobe', 'PG', 12, 123], ['Kareem', 'FW', 23, 345]]

lakers = Team(lakersdata, lakersplayers)

[snip]

p1 = lakers[1]
print p1.kitcolor

[snip]

lakers.kitcolor = 'blue'
print p1.kitcolor

[Not tested. I believe that the idea is clear]


  class RecruitmentError(ValueError):
      """Raised when a player cannot be recruited."""


  class Player(object):
      """A potential item of a Team() instance."""

      def __init__(self, playerdata, team=None):
          self.data = playerdata
          self.team = None
          if team:
              team.append(self)

      # (called when the usual attribute lookup didn't succeed)
      def __getattr__(self, name):
          return getattr(self.team, name)

      # ^ the last method may not be necessary -- you can always
      #   access to team data via 'team' attribute
      #   (and 'explicit is better than implicit')


  class Team(list):
      """A container for Player() instances."""

      def __init__(self, teamdata, playerdata=None):
          for key in teamdata:
              setattr(self, key, teamdata[key])
          for data in playerdata:
              self.append(Player(data))

      def _validate_and_get(self, index=None, player=None):
          if player is not None and not isinstance(player, Player):
              raise TypeError('A Player instance is required')
          if index is not None:
              if isinstance(index, slice):
                  raise TypeError('Slicing is not allowed')
              return self[index]  # (raise IndexError for bad index)

      _validate = _validate_and_get

      def _recruit(self, player):
          if player.team is None:
              player.team = self
          else:
              raise RecruitmentError('Player %s has already recruited')

      def _dismiss(self, player):
          player.team = None

      def __setitem__(self, index, player):
          current = self._validate_and_get(index, player)
          if player is not current:
              self._recruit(player)
              self._dismiss(current)
              list.__setitem__(self, index, player)

      def __delitem__(self, index):
          player = self._validate_and_get(index)
          self._dismiss(player)
          list.__delitem__(self, index)

      def append(self, player):
          self._validate(player=player)
          self._recruit(player)
          list.append(self, player)

      # and similarly:
      # * def extend...
      # * def insert...
      # * def pop...
      # * def remove...

...if you really need ordered container (reflecting functions/hierarchy
of players in a team?).

Otherwise, as Stephen noted, you should subclass set rather than list.

Cheers,
*j

--
Jan Kaliszewski (zuo) <z...@chopin.edu.pl>
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to