-2

Here the number of variables (which correspond to numfactors) are assigned manually to each letter of the alphabet. So the first variable is A and it gets assigned the value of an array slice (paths[0:35] for example). B is set to paths[35:70], repeat until the end. Now I could just make a very ugly if-then sequence for each possible letter, but it seems there has to be a better way. Current method:

import numpy as np
numfactors = 4
curvelen = 35
paths = np.random.randn(140)

indexes = list()
for i in range(numfactors):
    indexes.append("paths[" + str(curvelen*i) + ":" + str(curvelen*(i+1)) + "]")

A=eval(indexes[0])
B=eval(indexes[1])
C=eval(indexes[2])
D=eval(indexes[3])

Okay that's hardcoded, and 4 values are expected A, B, C, D. But the actual number could be 1 to 20 for example. Something like this:

for i in range(indexes):
# loop 1
   A=eval(indexes[i])
# loop 2
   B=eval(indexes[i])
# loop 3
   C=eval(indexes[i])
# ... to end

I think that summarizes the problem. Each loop goes through A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P etc. and assigns the letter-variable value to indexes[i] which is evaluated as a NumPy array slice. Any help is appreciated!

Update: thanks to @Diego Torres Milano and the linked post, this is all done in a few lines of code:

import string
import numpy as np

numfactors = 4
curvelen = 35
paths = np.random.randn(140)

# create path indexing for each input curve
indexes = list()
for i in range(numfactors):
    indexes.append("paths[" + str(curvelen*i) + ":" + str(curvelen*(i+1)) + "]")

# make a dictionary from A to Z for variables
variables = dict(zip(string.ascii_uppercase, indexes))

# assign each key name as variables (A-Z) to the paths defined prior
for k, v in variables.items():
    exec(f"{k} = {v}")

NOTE: I know using exec() and eval() are not safe. I actually have a great parser from here: https://blog.oyam.dev/python-formulas/ that I pass the (simplified) formulas to before evaluating them with exec(), so they are cleared as "okay" before the unsafe statements run.

Matt
  • 2,602
  • 13
  • 36
  • When you see many related variables, group them together in an array or dictionary. Carrying around so many variables is hard to manage. – qwr Jul 18 '22 at 01:00
  • You haven't provided a [mre], but assuming that you are just trying to create slices from a list and assign them unique names, you can do that with a dictionary and also avoid the complicated `eval()` that you are doing. – Craig Jul 18 '22 at 01:16
  • `from string import ascii_uppercase` may be useful to you~ – BeRT2me Jul 18 '22 at 01:21
  • Whatever it is you're trying to do, it's likely that making a dictionary is a far better option than dynamically creating variables. – BeRT2me Jul 18 '22 at 01:23
  • 1
    Also see [Why is using 'eval' a bad practice?](https://stackoverflow.com/questions/1832940/why-is-using-eval-a-bad-practice) and [Why should exec() and eval() be avoided?](https://stackoverflow.com/questions/1933451/why-should-exec-and-eval-be-avoided) – BeRT2me Jul 18 '22 at 01:25
  • eval is very bad practice and its only use is in obscure code golf backs. – qwr Jul 18 '22 at 01:37

2 Answers2

1

You can create a dictionary with uppercase letters as key using

import string
dict(zip(string.ascii_uppercase, indexes))
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
0
values = [eval(x) for x in indexes]
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P = values

This is assuming that the length of indexes is the same as the number of variables you are assigning.


So, I think I misunderstood what the user wanted. And I think what the user wants is a really, really bad idea. Python doesn't really want to create random variables on the fly, and it's really bad programming style to do that.

But you can get what you want with

>>> globals().update(zip(string.ascii_uppercase, values))

where values is as defined above.

Frank Yellin
  • 9,127
  • 1
  • 12
  • 22
  • Thank you that's an interesting trick you did here. I am having issues with the assignments to A, B, C, D, etc. as I don't want to manually type them for assignment. Using this example if I put in say A, B, C, D, E but there are only 3 values, `not enough values to unpack` – Matt Jul 18 '22 at 00:52