Reputation: 10936
Supose I have such variables: var1, var2, var3, var4, var 5, ..., var100 (lists and dictionaries are not suitable in my case, because all these vars are class objects).
I must process all them in similar way, for example:
if var1:
print 'var1 is not None'
if var2:
print 'var2 is not None'
if var3:
print 'var3 is not None'
...
if var100:
print 'var100 is not None'
In such way I will write 200 hundreds lines of code...
But maybe there is some way to process all of them in for
statement, like:
for i in range(1,101):
if var%s % i: #I know this is not right, but idea is understood
print 'var%s is not None' % i
So I will write only 3 lines of code.
Is it possible do in Python?
Thanks!
Upvotes: 3
Views: 422
Reputation: 601569
You can modify class attributes dynamically:
class A(object):
pass
for i in range(100):
setattr(A, "var%i" % i, i)
creates a class with 100 attributes called A.var0
to A.var99
. There are two problems with this approach:
The attributes are quite inconvenient to access. (This is possible with getattr()
, but having them in a list would make iterating over them so much easier.)
If class A
has a custom metaclass, it is unclear how that metaclass deals with the dynamically created attributes.
From a quick glance at the Django source code, I can see that django.db.models.Model
indeed has a custom metaclass, and indeed all attributes must already be defined at class creation time, so the above approach won't work. You'll have to create the complete class dictionary before actually creating the class. Here is one approach to do so:
model_dict = {}
for i in range(100):
model_dict["var%i" % i] = models.CharField(max_length=10)
model_dict["var_list"] = model_dict.values()
MyModel = type("MyModel", (models.Model,), model_dict)
This uses the three-parameter form of type()
to dynamically create a type. This part addresses problem 2.
To address problem 1, the above code exposes also adds an attribute to the class that allows to acces all the models.CharField
instances as a list rather than by name.
Upvotes: 2
Reputation: 6946
I think that a list or dictionary actually would be the most appropriate way to solve your problem. In Python, data structures can hold others objects. This includes objects that you create yourself because there is no technical distinction from the programmer's point of view between the types (classes) you define and the ones that are native to Python (string, int, etc.)
Upvotes: 1
Reputation: 1038
Couple different ways to do it, either get the variable from the globals or locals dictionary like so:
globals()['var1']
or import __main__
and use getattr(__main__,'var1')
throw those into a for loop, assigning the variable name to a string andhave it returned eg
if your testing that the class exists, use a try except
import __main__
for i in range(1,101):
try:
func = getattr(__main__,'var%s' % i)
if func is not None:
print 'var%s is not None' % i
except:
print 'var%s does not exist'
if it's buried in a class use the class name rather than __main__
. If the class name is var%s use getattr
on func
in the loop above to grab whatever it is you need out of each class.
Upvotes: 1
Reputation: 2038
I think you are looking for the eval command.
Hope this helps,
Regards, Maecky
Upvotes: 2
Reputation: 599580
I wish you hadn't buried your actual requirement in the tenth comment underneath the main question. Actually, it appears that what you want is to dynamically get a property of a class - in this instance, a field in a Django model. That's simple: you just do:
getattr(instance, varname)
Upvotes: 5
Reputation: 34704
locals()
returns a dictionary of local variables. Similarly, globals()
returns a dictionary of global variables. You can find the variable and its value in one of those, depending on where it was defined.
for i in range(1,101):
if ('var%s' % i) in locals():
print 'var%s is not None' % i
print locals()['var%s' % i]
Upvotes: 8