I don't know how many class instances I will have from the get-go, so I need to create them dynamically, but I would also like to keep the code tidy and readable.
I was thinking of doing something like this:
names = ['Jon','Bob','Mary']
class Person():
def __init__(self, name):
self.name = name
people = {}
for name in names:
people[name] = Person(name)
It works, but I can't seem to find any examples of people doing this online (though I didn't look much). Is there any reason I should avoid doing this? If so, why and what is a better alternative?
If you want to create class instances dynamically, which is exactly what you are doing in your code, then I think your solution looks perfectly fine and is a pythonic way to do so (although I have to say there are of course other ways). Just to give you some food for thought: you could register/store each new instance with the class like that:
class Person():
people={}
@classmethod
def create(cls,name):
person=Person(name)
cls.people[name]=person
return person
def __init__(self, name):
self.name = name
And if you are getting adventerous, you can try the same with metaclass, but I will leave that for your research :-)
Use type(name, bases, dict)
From documentation:
Return a new type object. This is essentially a dynamic form of the
class statement. The name string is the class name and becomes the
name attribute; the bases tuple itemizes the base classes and becomes the bases attribute; and the dict dictionary is the
namespace containing definitions for class body and becomes the
dict attribute. For example, the following two statements create identical type objects:
>>> class X(object):
... a = 1
...
>>> X = type('X', (object,), dict(a=1))
For your example:
>>> JonClass = type('JonClass', (object,), {'name': 'Jon'})
>>> jon_instance = JonClass()
>>> jon_instance.name
'Jon'
>>> type(jon_instance)
<class '__main__.JonClass'>
How about using a generator expression to create the dictionary?
people = dict((name, Person(name)) for name in names)
But besides this your solution is perfectly valid.