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