3

I'm a little new to Python, and was hoping that someone might be able to help me with a problem I've got.

I have the need to instantiate multiple objects using the variables in a list. Let's say I have a list of 2 items, ["apple", "orange"] and I want to use theses as names for a instantiated class based on class Fruit, so that I end up with 2 objects, apple and orange which are of class Fruit.

I've tried doing this but I can't seem to figure out how to use the variable name as the name of the instantiated class. This code doesn't work, but might give you some idea as to what I'm trying to achieve:

class Fruit:
    pass

my_list = ["apple", "orange"]

for item in my_list:
    item = Fruit()

type(apple)

This doesn't work but I hope that this gives you an idea as to what I'm trying to achieve. I get this error:

NameError: name 'apple' is not defined

What I would like to see is:

>>> type(apple)
<type 'instance'>

Any pointers that anyone can offer would be most appreciated :)

Thanks!

Simplified
  • 53
  • 1
  • 6
  • 4
    Don't. Keep your data out of your variable names. Use a dictionary instead (`fruits = {}`, then `fruits[item] = Fruit()`). – Martijn Pieters Apr 11 '14 at 11:22
  • +10 to Martijn's comment. This is one of the most persistent ideas most people (including me) had to get out of our heads to improve our code. – ojdo Apr 11 '14 at 11:44

2 Answers2

3

Dynamically creating variables is generally not a good idea. Just use a dictionary instead:

>>> fruits = {}
>>> for item in my_list:
...    fruits[item] = Fruit()
... 

>>> [(k, type(v)) for k, v in fruits.items()]
[('orange', <class '__main__.Fruit'>), ('apple', <class '__main__.Fruit'>)]

I suppose you could do a similar thing in the global scope by playing with globals(), but I would consider that very bad practice.

anon582847382
  • 19,907
  • 5
  • 54
  • 57
1

Very simple really, first make your base a new-style class:

class Fruit(object):
    pass

Then dynamically create any subclass you wish:

Apple = type("Apple", (Fruit, ), dict())

Then instantiate it:

anapple = Apple()

type(anapple)
__main__.Apple

Thus you have apple, orange, etc, which are all kind of fruits.

If you don't need a common ancestor, you can derive your new class from object:

Apple = type("Apple", (object, ), dict())

Finally if you already have these classes defined, dynamically or statically you can look them up like this, part 1, same module:

class Apple: pass
class Orange: pass

for name in ["Orange", "Apple"]:
    instance = globals()[name]()

Here, globals is a function, thus first (), it returns a dictionary, then you look up your fruit in this dictionary, thus [] and then you get a class and you instantiate it with ().

Finally if all your fruits are defined in some module, e.g.:

# fruits.py
class Apple: pass
class Orange: pass

# user code
import fruits
anapple = getattr(fruits, "Apple")()
Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120