2012-05-08 2 views
0

Как выполнить итерацию по списку, имя которого будет динамически генерироваться?Итерировать список, когда имя списка динамически сгенерировано

boneList_head =['def_neck', 'def_armbase']#hard coded list 
itemType='head'# result of a user button press 
... 
def selectBones(): 
    global itemType 
    bones =('boneList_'+itemType)# evaluates as a string , not name of a list 
    for bone in bones: 
     cmds.select(bone, tgl=True) 

проблема кости становится оцениваемой как строка, когда мне это нужно, чтобы вычисляться как имя списка.

+4

Что случилось с передачей правильного списка в 'selectBones' в качестве аргумента? В зависимости от глобальных переменных, особенно для переключения между более глобальными переменными, имеет тенденцию приводить к хрупкому коду. –

+0

Близко отнесен к http://stackoverflow.com/q/230896/535275 –

+4

Можете ли вы просто поместить списки в словарь, основанный на их имени? – sje397

ответ

7

Динамически генерируемые имена переменных почти всегда являются плохим подходом. Используй словарь!

bonedict = {'boneList_head': ['def_neck', 'def_armbase']} 
itemType='head' 

def selectBones(itemType): 
    bones = bonedict['boneList_' + itemType] 
    for bone in bones: 
     cmds.select(bone, tgl=True) 

Пожалуйста, проигнорируйте мой предыдущий ответ (видимый в моей истории изменений), который был глупым - головокружительным, даже. Но я виню свою глупость от динамического названия переменных!

Позвольте мне подробнее рассказать о том, почему динамическое имя имен переменных - плохая идея.

  1. Поскольку динамическая переменная генерации маскирует определения имен переменных. Трудно сказать, что было определено, а что нет, поэтому легко случайно переопределить переменную. Это основной источник потенциальных ошибок.

  2. Поскольку динамические переменные манипуляции скрывают изменения состояния под другим уровнем обфускации. В некоторой степени это верно при создании словаря или списка. Но один ожидает списков и словарей, чтобы потребовать немного дополнительного мышления. Имена переменных, с другой стороны, должны быть простыми. Когда переменные определения и переопределения требуют глубокого понимания, что-то не так.

  3. Поскольку динамическая генерация переменных загрязняет пространство имен. Если у вас так много переменных, что вы должны их автоматически генерировать, они должны жить в своем собственном пространстве имен, а не в локалях функции, а определенно не в глобальном пространстве имен. В своем руководстве по стилю для ядра linux Линус Торвальдс советует, если функция имеет более 5-10 локальных переменных, you're doing something wrong.

  4. Потому что динамическая генерация переменных способствует high coupling, что плохо. Если вы назначаете значения в словаре, вы можете передать этот словарь вперед и назад, пока корова не вернется домой, и все, о чём нужно знать, - это словарь. Если вы динамически создаете имена переменных в глобальном пространстве имен модуля, то, если другой модуль хочет получить доступ к этим именам переменных, он должен знать все о том, как они были сгенерированы, какие другие переменные в этом модуле определены и т. Д. Кроме того, передача переменных вокруг становится намного сложнее - вам нужно передать ссылку на сам модуль, возможно, используя sys.modules или другие сомнительные конструкции.

  5. Поскольку динамическая генерация переменных является уродливой. eval выглядит аккуратно и чисто, но на самом деле это не так. Он может сделать что угодно. Функции, которые могут что-то сделать, плохи, потому что вы не можете сразу сказать, что они делают здесь. Четко определенная функция делает одно и делает это хорошо; Таким образом, всякий раз, когда вы видите эту функцию, вы точно знаете, что происходит. Когда вы видите eval, буквально ничего может случиться. В этом смысле eval похож на goto. problem с goto заключается в том, что вы не можете использовать его правильно; это для каждого возможного правильного использования goto, есть 500 000 000 ужасающих неправильных способов его использования.Я даже не буду обсуждать проблемы безопасности здесь, потому что, в конце концов, это не настоящая проблема с eval.

+0

Итерация по кортежу не принесет ничего полезного - OP ищет итерацию по списку, который * назван * 'boneList_head'. Я бы предпочли * исключить * за отличное предложение использовать словарь. –

+0

@AdamMihalcin, ах, да, совершенно так. Упс! – senderle

+0

Словарь работает, а также eval ('boneList_' + itemType). почему словарь выше? – Mambo4

0

Это уродливое рубить, но это работает ... (конечно, вы должны получить правильный модуль)

import sys 
boneList_head =['def_neck', 'def_armbase'] 
itemType='head' 
... 
def selectBones(): 
    global itemType 
    bones=vars(sys.modules["__main__"])['boneList_'+itemType] 
    for bone in bones: 
     cmds.select(bone, tgl=True) 

Это на самом деле не отличается от того, что другие люди говорят однако ... Мы используем vars для создания словаря, чтобы получить нужный вам список - почему бы просто не перевести словарь (или правильный список) в функцию selectBones в первую очередь?

2

Я согласен с другими комментариями в том, что ваш подход, вероятно, не самый лучший. Но следующее должно работать:

bones = eval('boneList_' + itemType) 

Это будет запускать интерпретатор питона на «boneList_head», и возвращает список.

ПРИМЕЧАНИЕ. Как упоминал Адам Михалсин в комментариях, вы должны быть очень осторожны в том, чтобы использовать только eval для данных, которым вы доверяете или которые были проверены. Злоумышленник может вводить произвольный код в переменную itemType для доступа к os и т. Д.

+3

Примечание для всех, кто просматривает это сообщение в будущем: ** НЕ используйте ** этот код, если 'itemType' - это любая строка, предоставленная пользователем (или иначе генерируется вне вашего контроля). Python 'eval' будет выполнять произвольный код, позволяя человеку, который генерирует' itemType', делать всевозможные неприятные вещи в вашей системе. –

+0

Вы не можете подчеркнуть комментарий @AdamMihalcin достаточно, однако, +1 для очень простого решения. – mgilson

+0

это работает, но также используется словарь. – Mambo4

Смежные вопросы