3

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!

13
  • 2
    I don't believe "lists and dictionaries are not suitable in [your] case". Why do you think so? Commented Nov 26, 2011 at 20:41
  • 1
    "lists and dictionaries are not suitable in my case" - unless it's an obscure requirement for an assignment (in that case, smack whoever came up with it), there's absolutely no reason to do so. Commented Nov 26, 2011 at 20:42
  • 1
    @VitaliPonomar: How is this relevant? Commented Nov 26, 2011 at 20:43
  • 1
    @VitaliPonomar: How does this mean lists and dicts aren't suitable? Class objects are first-class objects, they can be stored in data structures and generated dynamically. I don't know much about Django but unless they try to gather classes though static analysis (which would be incredibly stupid and unnecessary for all I know), all of this should also hold for Django classes. Commented Nov 26, 2011 at 20:44
  • 3
    @VitaliPonomar: This question is a typical instance of the XY problem. You aren't asking about your real problem, but rather about how to achieve a particular solution you tried, without explaining the real problem. Consider to add the real problem to the actual question. Commented Nov 26, 2011 at 21:19

6 Answers 6

8

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]
Sign up to request clarification or add additional context in comments.

1 Comment

It was defind as class properties
5

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)

1 Comment

getattr(user_obj, 'var1') - so simple?
2

I think you are looking for the eval command.

Hope this helps,

Regards, Maecky

4 Comments

eval is seldom a good solution. Oh, and a heads-up, it tends to attract downvotes here on stackoverflow.
Ok, this works fine for print method. But if I want to redefine it dynamically, how to use eval() in this case: for i in range(1,101): eval('var%s' % i) = str(i)+a
eval() is a very bad solution in this case.
@VitaliPonomar: If there are many fields in your model, and you want to do several operations on all of them, you should definitely put them in a list. Really, believe me. If the Django Model metaclass insists on them also being available as class attributes, well, they will also have to be class attributes, but this doesn't prevent you from putting them in a list.
2

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:

  1. 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.)

  2. 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.

3 Comments

Can you post a link to official docs where decribes this method?
@VitaliPonomar: I gave you the link to the documentation of type(). What else do you need more information on?
Maybe you are interested in this SO answer.
1

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.

Comments

1

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.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.