【问题标题】:Python - using a string in for in statement?Python - 在 for in 语句中使用字符串?
【发布时间】:2012-12-21 09:22:56
【问题描述】:

所以我知道这是一种解决方法,并且可能有更好的方法来做到这一点,但这是交易。我已经简化了收集这些信息的代码,并给出了可靠的值。

curSel = nuke.selectedNodes()
knobToChange = "label"
codeIn = "[value in]"

kcPrefix = "x"
kcStart = "['"
kcEnd = "']"

changerString = kcPrefix+kcStart+knobToChange+kcEnd


for x in curSel:
    changerString.setValue(codeIn)

但我得到了我想我会的错误 - 这是一个字符串没有属性“setValue”

因为如果我只输入 x['label'] 而不是 changerString,它就可以工作,但是即使 changer string 说的完全一样,它也会被读取为字符串而不是代码。

有什么想法吗?

【问题讨论】:

  • 也许能做到for x in curSel: 然后for key, value in enumerate(x): ...你能举一些curSel值的例子吗?
  • 对不起,你能解释一下吗?没有得到那个
  • 为什么要将单个字符串的值设置为 n 次?你到底想在这里完成什么?
  • 它不是一个单一的项目...我在一个程序中选择了许多节点,并且 for 循环是您循环更改其中所有内容的方式。我想将多个更改为相同的值,因为 [value in'(我将其更改为)会对每个项目产生不同的影响。
  • 您是真的想将[value in] 放在每个节点的标签槽中,还是我误读了这个?

标签: python string for-loop expression


【解决方案1】:

看起来您正在寻找一些东西来根据您当前的命名空间将字符串评估为 python 对象。一种方法是使用globals 字典:

globals()['x']['label'].setValue(...)

换句话说,globals()['x']['label']x['label'] 是一回事。

或者根据您的情况明确说明:

globals()[kcPrefix][knobToChange].setValue(codeIn)

其他人可能会建议eval

eval('x["label"]').setValue(...)  #insecure and inefficient

globals 在这里绝对是一个更好的主意。


最后,通常当你想做这样的事情时,你最好首先使用字典或其他类型的数据结构来让你的数据更有条理

【讨论】:

  • +1 表示最后一句话。在 99% 的情况下,这两者都不是一个好主意。
  • 不,这不起作用,我这样做的原因是它基于用户输入......如果我只想输入 x.['label'] 我可以这样做。
  • 基本上我说的是必须使用 changerString 来获取 x['label'] ,因为 label 可以根据用户输入更改为任何内容。
  • @user1917081 -- 那为什么不:globals()['x'][user_input].setValue()?我不确定我是否理解您的限制...
  • 它不像我是 python 新手并且不明白 glboals 在做什么那样的约束。
【解决方案2】:

Righto,有两件事让你犯了错误。首先,在您尝试对字符串执行 setValue() 调用的原始代码中,您是对的,因为它不起作用。理想情况下使用两个调用之一(x.knob('name_of_the_knob')x['name_of_the_knob'],以与您的项目/设施/个人风格一致的方式)来获取和设置旋钮对象的值。

在 cmets 中,您的代码如下所示(我的 cmets 添加给其他不熟悉 Nuke 的人):

# select all the nodes
curSel = nuke.selectedNodes() 

# nuke.thisNode() returns the script's context 
# i.e. the node from which the script was invoked
knobToChange = nuke.thisNode()['knobname'].getValue() 
codeIn = nuke.thisNode()['codeinput'].getValue() 

for x in curSel: 
    x.knob(knobToChange).setValue(codeIn) 

使用此示例 UI 与所示的两个字段中的值以及触发脚本的按钮...

...当你执行它时,这段代码会给你一个错误消息'Nothing is named "foo"',因为.getValue() 调用实际上是返回你的评估结果旋钮 - 这是错误消息,因为它尝试执行 TCL [值 foo],并发现没有任何名为 foo 的对象。

理想情况下,您应该调用返回原始文本的 .toScript()

# select all the nodes
curSel = nuke.selectedNodes() 

# nuke.thisNode() returns the script's context 
# i.e. the node from which the script was invoked
knobToChange = nuke.thisNode()['knobname'].toScript() 
codeIn = nuke.thisNode()['codeinput'].toScript() 

for x in curSel: 
    x.knob(knobToChange).setValue(codeIn) 

您可以回避这个问题,正如您所指出的那样,根据您的原始代码构建一个字符串、添加方括号等从字符串构建对象(@mgilson 解释了如何在 globals()eval() 方法中进行操作)


对于那些没有享受过使用 Nuke 的乐趣的人,这里有一个小屏幕截图,它可能(或可能不......)提供更多背景信息:

【讨论】:

  • 要明确——我并不是真的鼓励“构建”字符串并转换为对象方法 (eval)。我什至不鼓励“获取对象的名称并使用它来获取对象的句柄”方法(@​​987654332@)——尽管这比eval 好得多。我鼓励“使用适当的数据结构”方法:)
  • @mgilson 我的错。重写了答案(因为我们现在对这个问题有了更好的处理)并更清楚地说明了你并没有将 globals 或 eval 方法作为 good 想法:)
  • 谢谢,这清理了很多,我不知道 toScript() 命令!这将非常方便。
  • 它并没有完全从 API 参考中跳出来,但如果你知道在哪里看(并建立连接,你作为文本旋钮输入的内容被称为“EvalString_Knob”对象..)它有点帮助:)
猜你喜欢
  • 1970-01-01
  • 2017-04-24
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 2021-11-21
  • 1970-01-01
相关资源
最近更新 更多