[Solved] The old version of Python caused my exercise to fail

Current installation of the Python 3.10 is having a defect that prevents me to implement the Space Age exercise
To simplify, this is a demonstration of the defect. The same way as in the code below I wanted to add dynamically a member functions using lambdas, but this doesn’t work. I tried this in 3.10 and then, consequently on 3.9 and 3.11 - in these two defect is not repro.

list_tuples=[
    ('test1', 'result1'),
    ('test2','result2')
]

class Test:
    def _my_calc(self, x):
        return self.s+'_'+x
    def __init__(self, s, is_bug):
        self.s = s

        if is_bug:
            for p in list_tuples:
                setattr(self, 'on_'+p[0], lambda: self._my_calc(p[1]))
        else:
            setattr(self, 'on_test1', lambda: self._my_calc('result1'))
            setattr(self, 'on_test2', lambda: self._my_calc('result2'))

print ('This is working as expected:---------------------------')
print (Test('OK on test1:', False).on_test1())
print (Test('OK on test2:', False).on_test2())
print ('But this is not:--------------------------------------')
print (Test('OK on test2:', True).on_test2())
print (Test('WTF is wrong with test1?:', True).on_test1()) 

So to be clear, this is an exercise you are writing and not the official one?

It would be helpful to indicate what the error is, ie paste the complete and full error message.

If you’re asking about a solution you tried to use for the exercise, it would be helpful to share the code you actually used to solve the exercise.

The code you shared gives me the same results in Py3.9 and 3.10; I’m not sure what issue you may be seeing.

To be clear, this is my code for the exercise:

planets=[
    ('mercury', 0.2408467),
    ('earth',1.0),
    ('venus', 0.61519726),
    ('mars', 1.8808158),
    ('jupiter', 11.862615),
    ('uranus', 84.016846),
    ('saturn', 29.447498),
    ('neptune', 164.79132)
]
class SpaceAge:
    def _my_calc(self, coeff):
        return round (self.seconds/(coeff * 31557600), 2)
    def __init__(self, seconds):
        self.seconds = seconds
        for p in planets:
            setattr(self, 'on_'+p[0], lambda: self._my_calc(p[1]))

My version was Python 3.10.6
and it is surely reproduced. Please see my answer to the next response - the exercise is failing in exercism.io as well.

1 Like

Well running it on the website so is the issue quite apparent. Lambda in that situation only takes the last value of the for loop which would be Neptune.

I would kinda recommend to avoid lambda in this situation. And instead move it.

1 Like

Hey, folks. I am sorry for the confusion. It is actually consistent between 3.10.6 and 3.11.0
Late binding lambda case, it is “as expected” (not as expected by me, but this is a problem between the chair and the keyboard.) Sorry!!! :pray:

2 Likes

Late Binding Variables: It’s a Trap! | by Hywel Carver | Skiller Whale | Medium :slight_smile:

1 Like