0

I'm trying to define a function in a Python class using lambda and I want to refer to the instance of the class from which it's being called and can't figure out how.

properties.append(pf.moleculeProperties())
properties[-1].name = "Monatomic Hydrogen"
properties[-1].formula = "H"
properties[-1].mass = (1.00795e-3)/(6.022e23)
properties[-1].elecLevels = [[pf.waveNumToJoules(82309.58), 1]]
properties[-1].q = lambda T,V : pf.q_trans(properties[-1],T,V) * pf.q_elec(properties[-1],T,V)

properties.append(pf.moleculeProperties())
properties[-1].name = "Monatomic Oxygen"
properties[-1].formula = "O"
properties[-1].mass = (16.0e-3)/(6.022e23)
properties[-1].elecLevels = [[pf.waveNumToJoules(158.265), 1], [pf.waveNumToJoules(226.977), 1], [pf.waveNumToJoules(15867.862), 1],
           [pf.waveNumToJoules(33792.583), 1], [pf.waveNumToJoules(73768.200), 1], [pf.waveNumToJoules(76794.978), 1], [pf.waveNumToJoules(86625.757), 1]]
properties[-1].q = lambda T,V : pf.q_trans(properties[-1],T,V) * pf.q_elec(properties[-1],T,V)

When I try to call q on the something other than the last member of the list, it seems to evaluate the properties[-1] statement and give me the last member of the list each time. In this example, I'm trying to call the q function on the element corresponding to hydrogen and getting the q function for oxygen.

John Stanford
  • 993
  • 1
  • 7
  • 18
  • 1
    Possible duplicate of [What do (lambda) function closures capture in Python?](http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python) – Kevin Aug 05 '16 at 05:32
  • I'm thinking you can get the scoping you want if you assign the lambda *inside* `pf.moleculeProperties`. – A. Vidor Aug 05 '16 at 05:34
  • minimal, reproducible example ... or a Gordian Knot of irrelevant, formulas within which is buried somewhere the pertinent programming problem that might be of use to someone else if they could spare the time to unpick it? – markling May 31 '19 at 09:15

1 Answers1

2

You need to evaluate properties in the argument list rather than the body of the lambda so that it binds early. So, define q as:

properties[-1].q = lambda T,V,self=properties[-1] : pf.q_trans(self,T,V) * pf.q_elec(self,T,V)

When you do the above, the assignment to self is evaluated once and becomes bound permanently to the lambda. Otherwise, properties will refer to the parent context (as you've found out).

Gary Wisniewski
  • 1,080
  • 10
  • 9