2

I have several variables that are named as so:

self.box_1
self.box_2
self.box_3
self.square_1
self.square_2
self.square_3
self.triangle_1
self.triangle_2
self.triangle_3

I want to create a dictionary of all the 'box','squares','triangles' and a dictionary of all the 1,2 and 3 of those.

Something like:

names = {'box':[self.box_1,self.box_2,self.box_3],
         'square':[self.square_1,self.square_2 ...}
numbers = {1:[self.box_1,self.square_1,self.triangle_1] 
           2:[self.box_2,self.square_2,... }

I've manage to make a small script to create the right string:

groups = ['box','square','triangle']

names = {}
for group in groups:
    g = []
    for n in xrange(1, 4):
        g.append('self.%s_%s' % (group, n))
    names[group] = g

numbers = {}
for n in xrange(1, 4):
    g = []
    for group in groups:
        g.append('self.%s_%s'%(group,n))
    numbers[n] = g

print "Names =",names
print "Number =",numbers

Output:

Names = {'box': ['self.box_1', 'self.box_2', 'self.box_3'], 'square': ['self.square_1', 'self.square_2', 'self.square_3'], 'triangle': ['self.triangle_1', 'self.triangle_2', 'self.triangle_3']}
Number = {1: ['self.box_1', 'self.square_1', 'self.triangle_1'], 2: ['self.box_2', 'self.square_2', 'self.triangle_2'], 3: ['self.box_3', 'self.square_3', 'self.triangle_3']}

As you can see, it's almost the same as the desired, but the names of the variables are in string format. How can I convert a string to a variable name?

f.rodrigues
  • 3,499
  • 6
  • 26
  • 62

3 Answers3

2

You need to use the getattr() function to dynamically retrieve attributes from an object:

names = {}
for group in groups:
    g = []
    for n in xrange(1, 4):
        g.append(getattr(self, '%s_%s' % (group, n))
    names[group] = g

However, consider using lists or dictionaries for your attributes instead; you can always index into those. self.box[0] is just as easy as self.box_1, but now you don't have to dynamically generate attribute names just to access all boxes.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks, that's exactly what I was looking for. The thing with the self.box_1 is from a Qt program I'm making, I've created several widgets items that have similar attributes, but I made a single variable for each widget, I'll try to work around it and see if I can make them into a list. I'm new to GUI design so I'm going easy on that. Thanks – f.rodrigues Dec 02 '14 at 18:06
1

It's probably best to avoid doing this.

Instead of this:

self.box_1
self.box_2
self.box_3

you should have a single list that you can use like this:

self.box[0]
self.box[1]
self.box[2]

Then you will be able to do this:

names["box"] = self.box

for i in xrange(3):
    numbers[i] = []
    for thing in (self.box, self.square, self.triangle):
        numbers[i].append(thing[i])
rlms
  • 10,650
  • 8
  • 44
  • 61
0

I think this will do pretty close to exactly you say you'd like to accomplish. For simplicity I madenamesandnumbersbothdefaultdicts instead of plaindicts.

from __future__ import print_function
from collections import defaultdict
from pprint import pprint, pformat

# for testing purposes
class Box(object): pass
class Square(object): pass
class Triangle(object): pass

# global variables
shape_names = {'box', 'square', 'triangle'}
names = defaultdict(list)
numbers = defaultdict(list)

class MyClass(object):
    def __init__(self):
        self.box_1 = Box()
        self.box_2 = Box()
        self.box_3 = Box()
        self.square_1 = Square()
        self.square_2 = Square()
        self.square_3 = Square()
        self.triangle_1 = Triangle()
        self.triangle_2 = Triangle()
        self.triangle_3 = Triangle()

        # classify shape attributes created
        for name, value in self.__dict__.iteritems():
            prefix, suffix = name.split('_')
            if prefix in shape_names:
                names[prefix].append(value)
                numbers[int(suffix)].append(value)

obj = MyClass()
print('names:\n', pformat(dict(names)), sep='')
print()
print('numbers:\n', pformat(dict(numbers)), sep='')

Output:

names:                                                     
{'box': [<__main__.Box object at 0x02388BD0>,              
         <__main__.Box object at 0x02388BB0>,              
         <__main__.Box object at 0x02388B90>],             
 'square': [<__main__.Square object at 0x02388BF0>,        
            <__main__.Square object at 0x02388C10>,        
            <__main__.Square object at 0x02388C30>],       
 'triangle': [<__main__.Triangle object at 0x02388C90>,    
              <__main__.Triangle object at 0x02388C70>,    
              <__main__.Triangle object at 0x02388C50>]}   

numbers:                                                   
{1: [<__main__.Square object at 0x02388BF0>,               
     <__main__.Box object at 0x02388B90>,                  
     <__main__.Triangle object at 0x02388C50>],            
 2: [<__main__.Square object at 0x02388C10>,               
     <__main__.Box object at 0x02388BB0>,                  
     <__main__.Triangle object at 0x02388C70>],            
 3: [<__main__.Triangle object at 0x02388C90>,             
     <__main__.Square object at 0x02388C30>,               
     <__main__.Box object at 0x02388BD0>]}                 
martineau
  • 119,623
  • 25
  • 170
  • 301