puzzled by name binding in local function

Ulrich Eckhardt ulrich.eckhardt at dominolaser.com
Tue Feb 5 10:18:10 EST 2013


Hello Pythonistas!

Below you will find example code distilled from a set of unit tests, 
usable with Python 2 or 3. I'm using a loop over a list of parameters to 
generate tests with different permutations of parameters. Instead of 
calling util() with values 0-4 as I would expect, each call uses the 
same parameter 4. What I found out is that the name 'i' is resolved when 
Foo.test_1 is called and not substituted inside the for-loop, which 
finds the global 'i' left over from the loop. A simple "del i" after the 
loop proved this and gave me an according error.

Now, I'm still not sure how to best solve this problem:
  * Spell out all permutations is a no-go.
  * Testing the different iterations inside a single test, is 
inconvenient because I want to know which permutation exactly fails and 
which others don't. Further, I want to be able to run just that one 
because the tests take time.
  * Further, I could generate local test() functions using the current 
value of 'i' as default for a parameter, which is then used in the call 
to self.util(), but that code is just as non-obviously-to-me correct as 
the current code is non-obviously-to-me wrong. I'd prefer something more 
stable.


Any other suggestions?

Thank you!

Uli


# example code
from __future__ import print_function
import unittest

class Foo(unittest.TestCase):
     def util(self, param):
         print('util({}, {})'.format(self, param))

for i in range(5):
     def test(self):
         self.util(param=i)
     setattr(Foo, 'test_{}'.format(i), test)

unittest.main()



More information about the Python-list mailing list