Q:

Change the value of a local variable where variable name will be expressed as a string

I am trying to find a good and secure way to call a variable using string substitution in order to set its value. This is a more best-practices and I am looking for the best possible way to do this.
First of all, using dictionary or similar structure is not what I want. I wish to set the value of a variable!
Example;
def test_my_var(name_param, val):
    # Set initial values for each variable
    my_var_1 = -1
    my_var_2 = -1
    my_var_3 = -1
    ...
    my_var_n = -1
   # Now I will update the value of mth variable 
   my_var_%{name_param}s = val  # Of course this will not work!!
   # Now print the new value of this variable
   print my_var_%{name_param}s

I am looking for a practical way to accomplish this. Things that are tested and do not work are:
I do not want to keep my vars in dict or similar structure. They are local variables inside a function and they should stay as they are. 
Using exec is not something I prefer since it will execute any command that is sent! So below is not a good way to go and is not a valid way.
def test_case(index, val):
    var_1 = -1
    var_2 = -1
    exec("var_%s" = %s % (index, val))
    print eval("var_%s" % index)  

Tested ways of using locals() and in setting the value, but fail to do so
def test_case(index, val):
    val_1 = -1
    val_2 = -1
    print locals()["val_%s" % index]
    locals()["val_%s" % index] = val
    print val_1, val_2  # That will not update the calue of the variable `val_1` or any other variable

So I am looking for a smart way to change the value of a variable where variable name will be expressed as a string substitution.

A:

You cannot do what you want, not within the constraints you set.
That's because locals() is not a live object. CPython uses a C array for the local variables, with the bytecode using indices to access them. The locals() dictionary is a convenience, a debugging tool, which pairs up the stored list of names for the locals with the values the array references. Trying to mutate that dictionary does not update the actual local variable array. 
As you figured out, exec does work, because Python 2 disables the optimisation for locals in that case and uses slower techniques the moment you add exec into the mix. In Python 3, exec() is no longer a statement but a function instead, and this loophole was closed. 
See globals() vs locals() mutability and Behavior of exec function in Python 2 and Python 3.
So if you are really looking for a best practice, stick with a dictionary or a list. These are locals too, but ones you can actually address the values in by string key or integer index.

