-1

I have several arrays:

foo_1 = [URL, 2, 30]
foo_2 = [URL, 4, 1230]
foo_3 = [URL, 11, 980]
foo_4 = [URL, 6, 316]

... I want to create a function that creates variables and renames them like so:

foo_1Count = foo_1[2]
foo_2Count = foo_2[2]
foo_3Count = foo_3[2]
foo_4Count = foo_4[2]

I am dealing with a very large set of arrays so creating the variables as such one by one isn't easy. I don't want to use a dictionary if I can help it. Is there a way to use .format() to create a variable name or something simple that I am missing? Thanks!

jttrail0
  • 1
  • 2
  • 2
    Why do you need separate variables? What's preventing you from storing counts in a flattened array (containing only the count fields)? – Jakub Jankowski Sep 01 '16 at 13:33
  • There are **many** Q&A's here on SO regarding dynamic variable name creation in Python and the consensus seems to be that there is no *good or proper* way to do it, and just use a dictionary. If you search SO you might find a clever solution using classes or metaclasses or some kind of class factory. [```operator.itemgetter()```](https://docs.python.org/3/library/operator.html#operator.itemgetter) might be useful, I like to use it. – wwii Sep 01 '16 at 14:00
  • 1
    When question is "I want arbitrary named variables" answer is "use a dict". When question is "I want variables named x1, x2, x3..." answer is "use a list". Easy, plain and simple, don't force a person who reads a code / static analyzer / IDE to guess which variables you're creating, there's absolute no profit in that. – Łukasz Rogalski Sep 01 '16 at 14:10
  • http://stackoverflow.com/q/1373164/2823755 – wwii Sep 01 '16 at 14:55

3 Answers3

1

If you're asking how to rename (understanding this action like create a new variable and deleting the existing old one) you could manipulate globals like this:

if __name__ == "__main__":
    URL = 'www.abc.com'

    foo_1 = [URL, 2, 30]
    foo_2 = [URL, 4, 1230]
    foo_3 = [URL, 11, 980]
    foo_4 = [URL, 6, 316]

    for i in range(4):
        old_name = 'foo_{}'.format(i + 1)
        new_name = 'foo_{}Count'.format(i + 1)
        globals()[new_name] = globals()[old_name][2]
        del globals()[old_name]

    print globals()

Now, I strongly recommend you not doing this! Don't mess with globals manually... Instead, if your variables have a similar structure, usually there isn't any good reason to declare them individually, you could pack them like this:

URL = 'www.abc.com'

foos = [
    [URL, 2, 30],
    [URL, 4, 1230],
    [URL, 11, 980],
    [URL, 6, 316]
]

foo_counts = [foo[2] for foo in foos]
print foo_counts

That way, you can iterate over your data nicely without having any cheap trick like messing around with globals.

BPL
  • 9,632
  • 9
  • 59
  • 117
0
URL = 'www.abc.com'

foo_1 = [URL, 2, 30]
foo_2 = [URL, 4, 1230]
foo_3 = [URL, 11, 980]
foo_4 = [URL, 6, 316]

for i in range(4):
        globals()['foo_{}Count'.format(i+1)] = globals()['foo_{}'.format(i+1)][2]

print foo_4Count    # 316
dragon2fly
  • 2,309
  • 19
  • 23
  • Awesome I appreciated all answers, but this is what I was looking for messing with my sets! Thanks a ton! – jttrail0 Sep 02 '16 at 18:33
  • I spoke too soon, I am getting a KeyError: '0' – jttrail0 Sep 02 '16 at 19:58
  • @jttrail0 Can you add your new code into your question? Because according to your current one, if `KeyError` happens, it should be `KeyError: 'foo_something'` not just `'0'`. Also please check all your indexes and beware that your `foo_%d` starts from `1`, not `0` while `range(n)` starts from `0` and end at `n-1` – dragon2fly Sep 04 '16 at 02:35
0

Dynamically creating variables is usually not a good idea. Instead, you can just get the attribute from the aggregating list object directly. It's even shorter than foo_1Count:

>>> foo_1 = ["URL", 2, 30]
>>> foo_1[2]
30

But you might not want to memorize which index was the count. Alternatively, create a function:

>>> def count(foo):
...     return foo[2]
... 
>>> count(foo_1)
30

Or make your foo objects dictionaries:

>>> foo_1 = {"url": "URL", "whatever": 2, "count": 30}
>>> foo_1["count"]
30

Or use collections.namedtuple to make it a bit cleaner:

>>> Foo = collections.namedtuple("Foo", ["url", "whatever", "count"])
>>> foo_1 = Foo("URL", 2, 30)
>>> foo_1.count
30
tobias_k
  • 81,265
  • 12
  • 120
  • 179