0

我对 Python 还很陌生,似乎无法让它发挥作用。我有一个列表,其中包含一个嵌入的对象列表,这些对象是函数的名称,我需要执行对象列表。我有调用函数列表的函数。我想改变它,这样我就可以直接调用函数列表而不调用另一个函数。

validActions=[
  ['Refresh','Environment Refresh',Refresh],
  ['Retire','Environment Retire Storage',
    [ doStatusDecommission,
      doPauseJobBeforeStart,
      doRetireStorage,
      doStatusDisconnected]],
  ['Provision','Environment Provision Storage',Provision]
]

def updateEnv(ctx):
  for actionVal,actionDesc,actionFunction in validActions:
    if ctx["newAction"] == actionVal:
      actionFunction()

如果我调用“Refresh”或“Provision”,因为它们是函数,则此方法有效。但是,当我调用“退休”列表并且错误消息是

TypeError: 'list' object is not callable
4

5 回答 5

3

您仍然可以调用列表中的每个函数。如果您制作所有条目列表,那么处理这两种情况会变得更加容易:

validActions=[
    ['Refresh','Environment Refresh', [Refresh]],
    ['Retire','Environment Retire Storage', [
        doStatusDecommission,
        doPauseJobBeforeStart,
        doRetireStorage,
        doStatusDisconnected
    ]],
    ['Provision', 'Environment Provision Storage', [Provision]]
]

def updateEnv(ctx):
    for actionVal, actionDesc, actionFunctions in validActions:
        if ctx["newAction"] == actionVal:
            for action_function in actionFunctions:
                action_function()

如果您所做的只是找到匹配的一个ctx['newAction']动作,那么您最好使用字典并直接从该 * 中查找actionDesc和项目:actionFunctions

validActions = {
    'Refresh': ('Environment Refresh', (Refresh,)),
    'Retire': ('Environment Retire Storage', (
        doStatusDecommission,
        doPauseJobBeforeStart,
        doRetireStorage,
        doStatusDisconnected
    ),
    'Provision': ('Environment Provision Storage', (Provision,)),
}

def updateEnv(ctx):
    actionDesc, actionFunctions = validActions[ctx["newAction"]]
    for action_function in actionFunctions:
         action_function()
于 2013-08-13T21:30:40.217 回答
1

制作所有这些列表,然后遍历列表依次执行每个列表。

for actionVal,actionDesc,actionFunctions in validActions:
  if ctx["newAction"] == actionVal:
    for actionFunction in actionFunctions:
      actionFunction()
于 2013-08-13T21:27:19.510 回答
1

一种选择是让每个列表以函数列表结尾,即使列表只有一个元素

validActions=[
  ['Refresh','Environment Refresh', [Refresh]], #note brackets around Refresh
  ['Retire','Environment Retire Storage',
    [ doStatusDecommission,
      doPauseJobBeforeStart,
      doRetireStorage,
      doStatusDisconnected]],
  ['Provision','Environment Provision Storage',[Provision]]
]

def updateEnv(ctx):
  for actionVal,actionDesc,actionFunctions in validActions:
    if ctx["newAction"] == actionVal:
      for func in actionFunctions:
        func()

或者创建一个调用所有 4 个函数的新函数

def retireFunctions():
  doStatusDecommission()
  doPauseJobBeforeStart()
  doRetireStorage()
  doStatusDisconnected()

validActions=[
  ['Refresh','Environment Refresh',Refresh],
  ['Retire','Environment Retire Storage', retireFunctions],
  ['Provision','Environment Provision Storage',Provision]
]

或者最后一个选项是类型测试(不推荐)

def updateEnv(ctx):
  for actionVal,actionDesc,actionFunction in validActions:
    if ctx["newAction"] == actionVal:
      if callable(actionFunction):
        actionFunction()
      else:
        for func in actionFunction:
          func()
于 2013-08-13T21:31:34.767 回答
0

我不想用您定义的列表填写我的答案以使其看起来更长。我将使用您定义的相同列表。

def updateEnv(ctx):
    for actionVal,actionDesc,actionFunctions in validActions:
        if ctx["newAction"] == actionVal:
            try:
                [func() for func in actionFunctions]
            except TypeError:
                # not iterable
                actionFunctions()
            except Exception as e:
                # iterable, unexpected errors
                print e
                pass

如果可以修改数据结构,我建议如下:

validActions={
  ('Refresh','Environment Refresh') : {Refresh},
  ('Retire','Environment Retire Storage'):
    { doStatusDecommission,
      doPauseJobBeforeStart,
      doRetireStorage,
      doStatusDisconnected } ,
  ('Provision','Environment Provision Storage'):{Provision}
}

您的函数通常是方法描述符,它们是不可变的。使用 set 作为函数的容器可以大大减少迭代和计数的时间成本。

通过使用字典作为带有元组键的顶级容器,您可以准确地将输入映射到输出。这意味着什么?它的意思是:

def updateEnv(ctx):
    [[func() for func in value] if ctx["newAction"] == key[0] 
     else None
     for key, value in validActions.items()]

更有效的是,如果您知道 actionDecs 是 actionVal 独有的,请使用两个单独的映射:

validActions = {
   'Refresh' : {Refresh},
   'Retire':
      { doStatusDecommission,
       doPauseJobBeforeStart,
       doRetireStorage,
       doStatusDisconnected } ,
   'Provision' : {Provision}
}

actionsDescs = {
    'Refresh': 'Environment Refresh'
    'Retire': 'Environment Retire Storage'
    'Provision' : 'Environment Provision Storage'
}

如果您需要从缩写描述,例如调用:

actionsDescs['Refresh']

你的函数迭代变成:

def updateEnv(ctx):
    [func() for func in validAction[ctx["newAction"]]]

如果您对此有特定需求或问题,请随时发表评论。

于 2013-08-13T23:12:53.040 回答
-1

按名称获取函数

如果此模块中定义的函数:

globals().get(actionFunctionName)(args)

如果在其他模块或类中:

getattr(class_or_module,actionFunctionName)(args)
于 2013-08-13T21:28:52.987 回答