-3

I am relatively new to Python and am asking myself if it is possible to create classes where names are dynamically created within a function?

Code:

def create_dummy_elements():
    rows = [A,B,C,D,E,F,G,H,I]
    columns = [A,B,C,D,E,F,G,H,I]

    for r in range (rows):
        for c in range (columns):
            ***** = element(1,1,1,False)

My result should be 81 objects of the class "element" named like AA,AB,AC,AD, ... * is what I am actually asking for ...

dcaswell
  • 3,137
  • 2
  • 26
  • 25
Sans
  • 9
  • 1
  • Do you wanna create a python file with those classes in the file ? or you want to create different instances of that class? – jramirez Oct 24 '13 at 21:49
  • 2
    It would be simpler to set up a dictionary of `element`s indexed by the names you want. Then once it's set up you could say for instance `elems['AA']` to get the `AA` element. – atomicinf Oct 24 '13 at 21:50
  • 2
    Your example doesn't illustrate this part "create classes which names are dynamically created within a function" – oleg Oct 24 '13 at 21:53
  • http://stackoverflow.com/questions/2320945/python-using-vars-to-assign-a-string-to-a-variable – zero323 Oct 24 '13 at 21:53
  • what You are asking for " if it is possible to create classes which names are dynamically created within a function." can be done with `type` function but example is for different question – oleg Oct 24 '13 at 21:55

3 Answers3

1

You can make a list of these objects, but it's not ideal to create variable names dynamically.

Something like this:

my_list_of_elements = []
for r in range (rows):
    for c in range (columns):
        my_list_of_elements.append(element(1,1,1,False))

Then you can access them by index number, for example: my_list_of_elements[n]

or to match the two-dimensional style for loops you have:

my_list_of_elements = []
for r in range (rows):
    temp = []
    for c in range (columns):
        temp.append(element(1,1,1,False))
    my_list_of_elements.append(temp)

then you can do my_list_of_elements[i][j] to access the i-th row and the j-th column.

If you prefer a string index, a dictionary would serve you well:

my_dict_of_elements = {}
for r in range (rows):
    for c in range (columns):
        my_dict_of_elements["element"+(r*c+c)] = element(1,1,1,False)

which will give you access like this my_dict_of_elements["element0"] for example.

As mentioned in the comment by atomicinf on this post, you can use the globals() dict, but it seems we both agree there are better practices.

Farmer Joe
  • 6,020
  • 1
  • 30
  • 40
  • 2
    Well, you _can_ create variable names dynamically (playing with the `globals()` dict), but there's really no reason to do that ever. – atomicinf Oct 24 '13 at 21:53
  • Oh forgot about that business, I'll fix my wording, but I don't think I would ever recommend that when you can just use a data structure. – Farmer Joe Oct 24 '13 at 21:55
1

I think you can just can create list as suggested farmerjoe, but if you really want to add namespases to global, you can do it like

class element(object):
    def __init__(self, *args):
        self._args = args
    def __repr__(self):
        return ' '.join(map(str, self._args))


rows = ['A','B']
columns = ['A','B']

for r in rows:
    for c in columns:
        exec('%s%s = element(r,c,False)' % (r,c))

print AB

output will be

A B False
alko
  • 46,136
  • 12
  • 94
  • 102
  • 1
    Aswering this way I feel myself handling a hand grenade to a monkey :) What do community think about too mature answers for on newbee's questions? – alko Oct 24 '13 at 22:06
  • Instead of `exec`, you could simply use `globals()[r+c] = element(r, c, False)`. Or better yet, create a reference to globals (to avoid repeatedly calling it, such as `_globals = globals()`), then using `_globals[r+c] = blah blah blah`. – Rushy Panchal Oct 24 '13 at 22:08
  • there is one caveat here, try globals()[4]=5 versus exec('4=5') – alko Oct 24 '13 at 22:10
0

Although it's possible to create classes and named instance of classes dynamically in Python, doing so is generally frowned upon. It's considered more "Pythonic" and elegant to store collections of such things in a container of some sort such as a list or dictionary, and then access them when necessary by index or key. Here's how that might apply to your problem:

class Element(object):
    def __init__(self, name, a=None, b=None, c=None):
        self.name, self.a, self.b, self.c = name, a, b, c
    def __str__(self):
        classname = self.__class__.__name__
        return('{classname}('
               'name={self.name}, b={self.a}, '
               'c={self.b}, d={self.c})'.format(classname=classname,
                                                self=self))
board = {}  # empty dictionary
for row in 'ABCDEFGHI':
    for col in 'ABCDEFGHI':
        name = row+col
        board[name] = Element(name)  # assign a named Element instance

# sample usage
board['AB'].a = 42
print board['AB']  # Element(name=AB, a=42, b=None, c=None)
board['GD'].c = 'something'
print board['GD']  # Element(name=GD, a=None, b=None, c=something)

Note: I don't really know what to call most of the attributes of the Element class, so am just using a, b, and c in the above for illustration purposes.

martineau
  • 119,623
  • 25
  • 170
  • 301