Re: Items inheriting attributes from its container?
Jan Kaliszewski wrote: [...] Great! Thanks to all of you for advices and code. K. -- http://mail.python.org/mailman/listinfo/python-list
Re: Items inheriting attributes from its container?
Kreso a écrit : 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' This is named "environmental aquisition" (or simply "aquisition") and is one of the base mechanisms in Zope 2. While an interesting idea, from experience, it can rapidly turn into a total maintainance nightmare if not used with care :-/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Items inheriting attributes from its container?
PS. Erratum: class Team(list): """A container for Player() instances.""" def __init__(self, teamdata, playerdata=None): *** Here should be added: list.__init__(self) *** for key in teamdata: setattr(self, key, teamdata[key]) for data in playerdata: self.append(Player(data)) -- Jan Kaliszewski (zuo) -- http://mail.python.org/mailman/listinfo/python-list
Re: Items inheriting attributes from its container?
23-08-2009 Kreso 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) -- http://mail.python.org/mailman/listinfo/python-list
Re: Items inheriting attributes from its container?
Kreso 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' > > The example appended below does that, but with the restriction that > container attributes must be set in the instantiation phase. This is > actually fine for me at the moment because my objects are "read only", but > I would like to hear about better solutions, with more flexibility, > please. > > > #-8< > 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) > > # This is fine: > p1 = lakers[1] > print p1.kitcolor > > # However the following doesn't work: > lakers.kitcolor = 'blue' > print p1.kitcolor > > #-8< I hope this gives you some good ideas. http://en.wikipedia.org/wiki/Join_(SQL) I suspect you will be finding a use for the special __getattr__ method, which is called when an attribute is not found. This can be used to search on your set of joined objects. Your list of joined objects should be a set() to prevent duplicates. -- Stephen Fairchild -- http://mail.python.org/mailman/listinfo/python-list
Re: Items inheriting attributes from its container?
Kreso schrieb: 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. The Python web application framework Zope implements the feature under the name "acquisition". Happy Googling! Christian -- http://mail.python.org/mailman/listinfo/python-list
Items inheriting attributes from its container?
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' The example appended below does that, but with the restriction that container attributes must be set in the instantiation phase. This is actually fine for me at the moment because my objects are "read only", but I would like to hear about better solutions, with more flexibility, please. #-8< 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) # This is fine: p1 = lakers[1] print p1.kitcolor # However the following doesn't work: lakers.kitcolor = 'blue' print p1.kitcolor #-8< -- http://mail.python.org/mailman/listinfo/python-list