3

I know this was asked a lot but I can not work with/understand the answers so far.

I want to change the suffix of variables in a for loop.

I tried all answers the stackoverflow search provides. But it is difficult to understand specific codes the questioner often presents.

So for clarification I use an easy example. This is not meant as application-oriented. I just want to understand how I can change the suffix.

var_1 = 10
var_2 = 100
var_3 = 1000

for i in range(1,4):
    test_i = var_i + 1
    print(test_i)

Expected result: creating and printing variables:

test_1 = 11 
test_2 = 101 
test_3 = 1001


Expected Output

11
101
1001

Error: var_i is read as a variable name without the changes for i.

4
  • 1
    If there were 100 values, do you create 100 variables? Use data structures to store values (ex: list). Commented Aug 18, 2019 at 16:18
  • There is a way to do this, but it's almost certainly not what you want. Have you heard of a list? Commented Aug 18, 2019 at 16:18
  • Use a dictionary or a list. As mentioned, this is basically always a Bad Idea™ Commented Aug 18, 2019 at 16:24
  • This puts into this conundrum. nedbatchelder.com/blog/201207/… Commented Aug 18, 2019 at 16:37

3 Answers 3

3

I would advise against using eval in 99.99% of all cases. What you could do is use the built-in getattr function:

import sys
var_1 = 10
var_2 = 100
var_3 = 1000

for i in range(1,4):
    test_i = getattr(sys.modules[__name__], f"var_{i}") + 1
    print(test_i)
Sign up to request clarification or add additional context in comments.

6 Comments

This looks painful but it works.<br> Just to make sure getattr(sys.modules[__name__], f"var_{i}") is my variable var_i right?
That's correct. sys.modules[__name__] is the current module, whereas `f"var_{i}" is var 1 to 3. And getattr is simply there to access the variables
the test_i line gives me a syntax error in python 2 and 3, and doesn't assign the variables test_1, test_2 etc, just re-uses test_i
@beroe the f-string syntax is python 3.6+. 2.7 is almost out the door (thankfully) and almost all major libraries do not support it anymore and I'd advise you to ditch it as well. I'd put 3.5 on the same boat as well given there's almost no movement there and it's original release was 5 years ago. I suggest you upgrade.
Thanks Alexander. The f-strings do look fun, but I forgot they were not in 3.5.
|
2

Instead of doing a convoluted naming convention, try to conceive of your problem using a data structure like dictionaries, for example.

var={}
var[1] = 10
var[2] = 100
var[3] = 1000

test={}
for i in range(1,4):
    test[i] = var[i] +1

print(test)

If somehow you are given var_1 etc as input, maybe use .split("_") to retrieve the index number and use that as the dictionary keys (they can be strings or values).


Small explanation about using indexing variable names. If you are starting out learning to program, there are many reasons not to use the eval, exec, or getattr methods. Most simply, it is inefficient, not scalable, and is extremely hard to use anywhere else in the script.

I am not one to insist on "best practices" if there is an easier way to do something, but this is something you will want to learn to avoid. We write programs to avoid having to type things like this.

If you are given that var_2 text as a starting point, then I would use string parsing tools to split and convert the string to values and variable names.

By using a dictionary, you can have 1000 non-consecutive variables and simply loop through them or assign new associations. If you are doing an experiment, for example, and call your values tree_1, tree_10 etc, then you will always be stuck typing out the full variable names in your code rather than simply looping through all the entries in a container called tree.

This is a little related to using a bunch of if:else statements to assign values:

# inefficient way -- avoid
if name == 'var_1' then:
    test_1=11
elif name == 'var_2' then:
    test_2=101

It is so much easier just to say:

test[i]= var[i]+1

and that one line will work for any number of values.

3 Comments

With this it just adds 10,100 and 100 to the list. It does not compute 10+1,100+1 and 1000+1.
Thanks. I fixed that but the point was just to show a possible alternative to all the eval answers.
Thank you for your explanation. Now with the correct code this seems the most readable, easiest and low-risk solution.
0
for i in range(1, 4):
   print(eval('var_' + str(i)))

Step by step:

1) Make your variables strings:

stringified_number = str(i)

2) evaluate your expression during runtime:

evaluated_variable = eval('var_' + stringified_number)

3 Comments

This produces the error: "NameError: name 'var_10' is not defined"
@MartinFlower just removed the part with the list
var_1 = 10 var_2 = 100 var_3 = 1000 for i in range(1, 4): test_i = eval('var_' + str(i)) + 1 print(test_i) Right. This works fine, Is understandable and good readable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.