This first version works fine. It will return a list of the same
length as "seq", composed of "seq[n].attrib" for all n, or else
'None' if there is no attribute of that name.
# we aren't going to try to catch TypeError: attribute-less object:
# we will consider that an actual error.
#
def collect1( seq, attrib ):
res = []
for x in seq:
try:
res.append( getattr( x, attrib ) )
except AttributeError:
res.append( None )
return res
# construct a dummy class and a test sequence:
class Test:
def __init__( self, thing ):
self.me = thing
self.str = str( thing )
self.what = eval( str( thing ))
testSeq = []
for x in range( 1, 10 ):
testSeq.append( Test( x ) )
testSeq.append( Test( `x` ) )
>>> collect1( testSeq, 'me' )
[1, '1', 2, '2', 3, '3', 4, '4', 5, '5', 6, '6', 7, '7', 8, '8', 9, '9']
This shorted, unsafe ( i.e. non-nil returning version ) looks
like it SHOULD work:
def collect2( seq, attrib ):
return map( lambda obj: getattr( obj, attrib ), seq )
- BUT if called from the defined function 'collect2', it gets
a name error on 'attrib' :
>>> collect2( testSeq, 'me' )
Traceback (innermost last):
File "<stdin>", line 1
File "./collect.py", line 16
return map( lambda obj: getattr( obj, attrib ), seq )
File "./collect.py", line 16
return map( lambda obj: getattr( obj, attrib ), seq )
NameError: attrib
- But if the map() is done from the command level, it DOES work:
>>> map( lambda obj: getattr( obj, 'me' ), testSeq )
[1, '1', 2, '2', 3, '3', 4, '4', 5, '5', 6, '6', 7, '7', 8, '8', 9, '9']
[ Am I wrong ? *SHOULDN'T* this work !_? ]
My guess is that this is some strange interaction of lambda with
the local binding in the subroutine. ( Lambda expects global
binding maybe ? )
I have tried several variants of assigning the formal arg to
another local value first, and even trying to pass 'repr(attrib)'
instead, with pretty much the same results.
Any comments ?
- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
- UVA Department of Molecular Physiology and Biological Physics