Python: как использовать переменные в виде строки? - PullRequest
3 голосов
/ 27 ноября 2011

Предположим, у меня есть такие переменные: var1, var2, var3, var4, var 5, ..., var100 (списки и словари в моем случае не подходят, потому что все эти переменные являются объектами класса).

Я должен обработать все их аналогичным образом, например:

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'

Так я напишу 200 сотен строк кода ...

Но, возможно, есть какой-то способ обработать их все в for выражении, например:

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

Так что я напишу только 3 строки кода.

Можно ли сделать в Python?

Спасибо!

Ответы [ 6 ]

8 голосов
/ 27 ноября 2011

locals() возвращает словарь локальных переменных.Точно так же globals() возвращает словарь глобальных переменных.Вы можете найти переменную и ее значение в одной из них, в зависимости от того, где она была определена.

for i in range(1,101):
    if ('var%s' % i) in locals():
        print 'var%s is not None' % i
        print locals()['var%s' % i]
5 голосов
/ 27 ноября 2011

Хотелось бы, чтобы вы не похоронили свое фактическое требование в десятом комментарии под основным вопросом.На самом деле, кажется, что вам нужно динамически получить свойство класса - в данном случае, поля в модели Django.Это просто: вы просто делаете:

getattr(instance, varname)
2 голосов
/ 27 ноября 2011

Я думаю, вы ищете команду eval .

Надеюсь, это поможет,

С уважением, Maecky

2 голосов
/ 27 ноября 2011

Вы можете динамически изменять атрибуты класса:

class A(object):
    pass
for i in range(100):
    setattr(A, "var%i" % i, i)

создает класс с 100 атрибутами с именами от A.var0 до A.var99.У этого подхода есть две проблемы:

  1. Атрибуты довольно неудобны для доступа.(Это возможно с getattr(), но наличие их в списке значительно упростит итерации по ним.)

  2. Если у класса A есть собственный метакласс, неяснокак этот метакласс имеет дело с динамически создаваемыми атрибутами.

Беглый взгляд на исходный код Django, я вижу, что django.db.models.Model действительно имеет собственный метакласс, и действительно все атрибуты должныуже определено во время создания класса, поэтому вышеупомянутый подход не будет работать.Вам придется создать полный словарь классов перед тем, как создавать класс.Вот один из подходов для этого:

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)

Используется трехпараметрическая форма type() для динамического создания типа.В этой части рассматривается проблема 2.

Чтобы решить проблему 1, вышеприведенный код также добавляет в класс атрибут, который позволяет получить доступ ко всем экземплярам models.CharField в виде списка, а не по имени.

1 голос
/ 27 ноября 2011

Я думаю, что список или словарь на самом деле был бы наиболее подходящим способом решения вашей проблемы.В Python структуры данных могут содержать другие объекты.Это включает объекты, которые вы создаете сами, потому что с точки зрения программиста нет никакого технического различия между типами (классами), которые вы определяете, и типами, которые являются родными для Python (string, int и т. Д.)

1 голос
/ 27 ноября 2011

Пара разных способов сделать это, либо получить переменную из словаря глобальных или локальных значений, например так: globals()['var1']

или import __main__ и использовать getattr(__main__,'var1')

, бросить их вцикл for, присвоив имя переменной строке и вернув ее, например,

, если вы проверяете, что класс существует, используйте 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'

, если он похоронен в использовании классаимя класса, а не __main__.Если имя класса var% s, используйте getattr on func в цикле выше, чтобы извлечь из каждого класса все, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...