Re: Finding attributes in a list

2005-04-02 Thread Marcus Goldfish
 class Player(object):
def __init__(self, **kw): self.__dict__.update(kw)
def __repr__(self): return 'Player %s'%getattr(self, 'name', 
 '(anonymous)')

 import operator
 [p.name for p in sorted(players, key=operator.attrgetter('attacking'), 
 reverse=True)]

Just happened to read this thread and wanted to say this is a neat
little example-- thank you!  I have a couple of followup questions.

   (1) Is there a performance penalty for using key=operator.attrgetter()?
   (2) The Player class looks like a nice model for a data table when one
wants to sort by arbitrary column.  Would you agree?
   (3) Suppose one wished to construct a player list from a collection of
attribute lists, e.g.,

names = ['bob', 'sam', 'linda']
attack = [7, 5, 8]
defense = [6, 8, 6]
# construct players list here

   Can you recommend an efficient way to construct the player list?

Thanks!
Marcus
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Finding attributes in a list

2005-04-02 Thread James Stroud
On Saturday 02 April 2005 08:44 pm, Marcus Goldfish wrote:
(2) The Player class looks like a nice model for a data table when one
 wants to sort by arbitrary column.  Would you agree?

The Player class is (and any class) is absolutely fabulous when you have 
heterogenous data (string, int, etc). I would not fall into the trap of LoDs 
(Lists of Dictionaries). They get unwieldy because you always have to manage 
them with functions. You end up writing a module built around your specific 
dictionary and you end up with a duct-taped object oriented design anyway. 
Classes are way better--so use them up front, even if you think that your 
data structure will never be complicated enough to warrant a class. It 
eventually will if it is worth a damn to begin with. Given this is a soccer 
team we are talking about, it is definitely worth being a full fledged class. 
However, if it were basketball...

(3) Suppose one wished to construct a player list...[snip]

team = [Player(azip[0],azip[1],azip[2]) for azip in zip(names,attack,defense)]


You have to love listcomp.

Better (IMHO) would be

  team = [Player(azip) for azip in zip(names,attack,defense)]

where a Player might come to life with

  class Player(object):
def __init__(self, atup):
  self.name, self.attack, self.defense = atup

BUT, even way better (again, IMHO) would be

  ateam = Team(zip(names,attack,defense))

where team could be initialized by a tuple:

  class Team(list):
def __init__(self, azip):
  for azip in alist:
self.data.append(Player(atup))

James

-- 
James Stroud, Ph.D.
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Finding attributes in a list

2005-04-02 Thread James Stroud
On Saturday 02 April 2005 09:51 pm, James Stroud wrote:
 where team could be initialized by a tuple:

   class Team(list):
     def __init__(self, azip):
       for azip in alist:
         self.data.append(Player(atup))

Sorry, this should read:

where team could be initialized by a list of tuples:

  class Team(list):
def __init__(self, azip):
  for atup in azip:
self.data.append(Player(atup))

-- 
James Stroud, Ph.D.
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
--
http://mail.python.org/mailman/listinfo/python-list


Re: Finding attributes in a list

2005-04-02 Thread Bengt Richter
On Sat, 2 Apr 2005 23:44:11 -0500, Marcus Goldfish [EMAIL PROTECTED] wrote:

 class Player(object):
def __init__(self, **kw): self.__dict__.update(kw)
def __repr__(self): return 'Player %s'%getattr(self, 'name', 
 '(anonymous)')

 import operator
 [p.name for p in sorted(players, key=operator.attrgetter('attacking'), 
 reverse=True)]

Just happened to read this thread and wanted to say this is a neat
little example-- thank you!  I have a couple of followup questions.

   (1) Is there a performance penalty for using key=operator.attrgetter()?
I would think sorted would make it as efficient as possible, but 
possibly.
I can conceive of low level optimization for key=some C builtin that 
can be recognized
But timing is best ;-) Also, vs what? There are a number of 
alternatives.

   (2) The Player class looks like a nice model for a data table when one
wants to sort by arbitrary column.  Would you agree?
 Depends on scale, and what else use you have for a custom object 
representation. E.g.,
 (using below lists available from interactive session below) a plain 
dict by names (unique required)
 with (attack, defense) tuples as values is probably pretty efficient 
and fast.

   dict(zip(names, zip(attack, defense)))
  {'linda': (8, 6), 'bob': (7, 6), 'sam': (5, 8)}

 But if objects are going to be complex and have methods or properties, 
OO makes it easy.

   (3) Suppose one wished to construct a player list from a collection of
attribute lists, e.g.,

names = ['bob', 'sam', 'linda']
attack = [7, 5, 8]
defense = [6, 8, 6]
# construct players list here

   Can you recommend an efficient way to construct the player list?

I wouldn't worry about efficiency unless you are dealing with a database of
all the worlds teams ;-) (And in that case, you probably want to look into
interfacing with the database your data is already in, to let it do things
for you natively e.g. via SQL).

If you know the columns as matching attribute lists as above, zip will 
associate them
into tuples. Also, I used a keyword argument in the Player __init__ above 
because I
wanted to copy and paste the dict calls from the prior post, but knowing exact 
columns,
I'd probably do some thing like:

  class Player(object):
 ... def __init__(self, name, attack=None, defense=None): # require name
 ... self.name = name
 ... self.attack = attack
 ... self.defense = defense
 ...
  names = ['bob', 'sam', 'linda']
  attack = [7, 5, 8]
  defense = [6, 8, 6]
 

Then the players list is just
  players = [Player(*tup) for tup in zip(names, attack, defense)]
where *tup unpacks a tuple from the output of zip into the arg list of Player's 
__init__.

And you can extract the names like
  [player.name for player in players]
 ['bob', 'sam', 'linda']

Or whatever you want
  for player in players: print player.name, player.attack, player.defense
 ...
 bob 7 6
 sam 5 8
 linda 8 6

As mentioned, zip makes tuples of corresponding elements of its argument lists:
  zip(names, attack, defense)
 [('bob', 7, 6), ('sam', 5, 8), ('linda', 8, 6)]

If you had huge input lists, you could avoid the terporary tuple list using
  import itertools
  iplayers = list(itertools.starmap(Player, itertools.izip(names, attack, 
  defense)))
  for player in iplayers: print player.name, player.attack, player.defense
 ...
 bob 7 6
 sam 5 8
 linda 8 6

You can look into __slots__ if you want to have objects but need reduced memory 
footprint.
But don't worry about optimizing 'til you can prove you need it, unless just 
for fun ;-)

Ok. That's enough relief for me. Got other stuff ...

Regards,
Bengt Richter
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Finding attributes in a list

2005-03-29 Thread infidel
You can use the new 'sorted' built-in function and custom compare
functions to return lists of players sorted according to any criteria:

 players = [
... {'name' : 'joe', 'defense' : 8, 'attacking' : 5, 'midfield' : 6,
'goalkeeping' : 9},
... {'name' : 'bob', 'defense' : 5, 'attacking' : 9, 'midfield' : 6,
'goalkeeping' : 3},
... {'name' : 'sam', 'defense' : 6, 'attacking' : 7, 'midfield' : 10,
'goalkeeping' : 4}
... ]
 def cmp_attacking(first, second):
... return cmp(second['attacking'], first['attacking'])
...
 [p['name'] for p in sorted(players, cmp_attacking)]
['bob', 'sam', 'joe']


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Finding attributes in a list

2005-03-29 Thread Bengt Richter
On Tue, 29 Mar 2005 11:29:33 -0700, Steven Bethard [EMAIL PROTECTED] wrote:

infidel wrote:
 You can use the new 'sorted' built-in function and custom compare
 functions to return lists of players sorted according to any criteria:
 
 
players = [
 
 ...  {'name' : 'joe', 'defense' : 8, 'attacking' : 5, 'midfield' : 6,
 'goalkeeping' : 9},
 ...  {'name' : 'bob', 'defense' : 5, 'attacking' : 9, 'midfield' : 6,
 'goalkeeping' : 3},
 ...  {'name' : 'sam', 'defense' : 6, 'attacking' : 7, 'midfield' : 10,
 'goalkeeping' : 4}
 ... ]
 
def cmp_attacking(first, second):
 
 ...  return cmp(second['attacking'], first['attacking'])
 ...
 
[p['name'] for p in sorted(players, cmp_attacking)]
 
 ['bob', 'sam', 'joe']

Or more efficiently, use the key= and reverse= parameters:

py players = [
...dict(name='joe', defense=8, attacking=5, midfield=6),
...dict(name='bob', defense=5, attacking=9, midfield=6),
...dict(name='sam', defense=6, attacking=7, midfield=10)]
py import operator
py [p['name'] for p in sorted(players,
...key=operator.itemgetter('attacking'),
...reverse=True)]
['bob', 'sam', 'joe']

Perhaps the OP doesn't yet realize that Python also provides the ability
to define custom classes to represent players etc. E.g., using instance 
attribute
dicts instead of raw dicts (to save typing ;-):

  class Player(object):
 ... def __init__(self, **kw): self.__dict__.update(kw)
 ... def __repr__(self): return 'Player %s'%getattr(self, 'name', 
'(anonymous)')
 ...
  players = [
 ... Player(name='joe', defense=8, attacking=5, midfield=6),
 ... Player(name='bob', defense=5, attacking=9, midfield=6),
 ... Player(name='sam', defense=6, attacking=7, midfield=10)]
  players
 [Player joe, Player bob, Player sam] 
  import operator
  [p.name for p in sorted(players, key=operator.attrgetter('attacking'), 
  reverse=True)]
 ['bob', 'sam', 'joe']

And then he could create a Team class which might have players as an internal 
list,
and provide methods for modifying the team etc., and generating various reports
or calculating and/or retrieving data. Not to mention properties for dynamically
caclulated attributes etc ;-)

Regards,
Bengt Richter
-- 
http://mail.python.org/mailman/listinfo/python-list