0

ANSWER AT THE END

I am trying to monkey patch a class with attributes that are assigned programatically, but I am running into a variable scope problem that I don't know how to solve. See the code below:

class my_obj_class:
    pass
my_obj = my_obj_class()

letters = ['a', 'b']
numbers = [1, 2]

for l in letters:
    for n in numbers:
        attribute_name = "print_" + l + str(n)

        def print_ln(self):
            print(l, n)

        setattr(my_obj_class, attribute_name, print_ln)

my_obj.print_a1()
l, n = "c", 3
my_obj.print_a1()

prints:

b 2
c 3

Obviously this isn't working the right way (print_a1 always prints "a1") because the print_ln is printing the variables l and n which are changing in the for loop and each attribute is using the same two variables. I can't seem to conceive how to do this so that print_a1 always prints "a1" and not a value of a variable other than to hard code each attribute, which I am obviously trying not to do.


ANSWER

Yes, thanks for the comments, the answer is closures, which are new to me. The for working loop is below:

for l in letters:
    for n in numbers:
        attribute_name = "print_" + l + str(n)

        def print_ln(l, n):
            def printer(self):
                print(l, n)
            return printer

        setattr(my_obj_class, attribute_name, print_ln(l, n))
Vince W.
  • 3,561
  • 3
  • 31
  • 59
  • 1
    Where's the `print_a1()` function? – Torxed Dec 19 '16 at 18:15
  • 1
    you have to surround your functions with a closure – kmaork Dec 19 '16 at 18:16
  • shouldn't you add the attributes to the instance `my_obj` instead of the class `my_obj_class`? – hiro protagonist Dec 19 '16 at 18:17
  • the print a1 function is defined in the for loops. l = 'a', n = 1, attribute_name = "print_" + l + str(n) --> print_a1, which is then added to the class with setattr – Vince W. Dec 19 '16 at 18:17
  • @hiro - that depends on what you want to do. Since I want all future instances to have these variables I add it to the class – Vince W. Dec 19 '16 at 18:18
  • @VinceWest: if you do not have an `__init__` function that sets them to a default value there is really no point in doing that. or do you mean to add member functions? – hiro protagonist Dec 19 '16 at 18:25
  • @hiro, the real working example is significantly more complicated. This was just an MVCE, but yes it is to add member functions (not variables) – Vince W. Dec 19 '16 at 18:34

0 Answers0