Python“switch语句”和字符串格式

时间:2010-09-24 01:19:27

标签: python lambda switch-statement

我正在尝试使用switch语句(使用字典),答案需要是格式化字符串,例如:

descriptions = {
   'player_joined_clan': "%(player)s joined clan %(clan)s." % {"player": token1, "clan": token2},
   #etc...
  }

现在,如果始终定义这两个令牌,这将起作用,但实际情况并非如此。另外我相信它是格式化字典中的所有字符串,这是不需要的,它应该只格式化所需的字符串。所以,我想出了使用lambda

这个非常不寻常和部分愚蠢的解决方案
descriptions = {
   'player_joined_clan': lambda x: "%(player)s joined clan %(clan)s." % {"player": token1, "clan": token2},
  }

然后我可以用descriptions["player_joined_clan"](0)调用它,它会按预期工作但是呃,如此丑陋和不直观......我显然在这里遗漏了一些东西。

提前感谢任何提示。

3 个答案:

答案 0 :(得分:3)

如果我理解正确,我建议collections.defaultdict。 这不是我所谓的“切换”声明,但我认为最终结果接近您所寻找的。

我可以用完整的代码,数据和应用程序来解释。 显然,关键是defualtdict线。

>>> import collections
>>> 
>>> descriptions = {
...     'player_joined_clan' : '%(player)s joined clan %(clan)s',
...     'player_left' : '%(player)s left',
...     'player_hit_player' : '%(player)s (of %(clan)s) hit %(player2)s (of %(clan2)s)',
...     }
>>> 
>>> data = [
...     {'player': 'PlayerA'},
...     {'player': 'PlayerB', 'clan' : 'ClanB'},
...     {'clan' : 'ClanC'},
...     {'clan' : 'ClanDA', 'player2': 'PlayerDB'},
...     ]
>>> 
>>> for item in data:
...     print item
...     item = collections.defaultdict(lambda : '"<unknown>"', **item)
...     for key in descriptions:
...         print '  %s: %s' % (key, descriptions[key] % item)
...     print
... 
{'player': 'PlayerA'}
  player_joined_clan: PlayerA joined clan "<unknown>"
  player_left: PlayerA left
  player_hit_player: PlayerA (of "<unknown>") hit "<unknown>" (of "<unknown>")

{'clan': 'ClanB', 'player': 'PlayerB'}
  player_joined_clan: PlayerB joined clan ClanB
  player_left: PlayerB left
  player_hit_player: PlayerB (of ClanB) hit "<unknown>" (of "<unknown>")

{'clan': 'ClanC'}
  player_joined_clan: "<unknown>" joined clan ClanC
  player_left: "<unknown>" left
  player_hit_player: "<unknown>" (of ClanC) hit "<unknown>" (of "<unknown>")

{'clan': 'ClanDA', 'player2': 'PlayerDB'}
  player_joined_clan: "<unknown>" joined clan ClanDA
  player_left: "<unknown>" left
  player_hit_player: "<unknown>" (of ClanDA) hit PlayerDB (of "<unknown>")

或者,如果您希望它比仅包含一个字符串的lambda更具可定制性,您可以定义自己的defaultdict类,例如:

class my_defaultdict(collections.defaultdict):
    def __missing__(self, key):
        return '<unknown %s>' % key

更改该行以使用您的类而不是默认类:

#item = collections.defaultdict(lambda : '"<unknown>"', **item)
item = my_defaultdict(**item)

,瞧,输出:

{'player': 'PlayerA'}
  player_joined_clan: PlayerA joined clan <unknown clan>
  player_left: PlayerA left
  player_hit_player: PlayerA (of <unknown clan>) hit <unknown player2> (of <unknown clan2>)

{'clan': 'ClanB', 'player': 'PlayerB'}
  player_joined_clan: PlayerB joined clan ClanB
  player_left: PlayerB left
  player_hit_player: PlayerB (of ClanB) hit <unknown player2> (of <unknown clan2>)

{'clan': 'ClanC'}
  player_joined_clan: <unknown player> joined clan ClanC
  player_left: <unknown player> left
  player_hit_player: <unknown player> (of ClanC) hit <unknown player2> (of <unknown clan2>)

{'clan': 'ClanDA', 'player2': 'PlayerDB'}
  player_joined_clan: <unknown player> joined clan ClanDA
  player_left: <unknown player> left
  player_hit_player: <unknown player> (of ClanDA) hit PlayerDB (of <unknown clan2>)

有关更多示例,请参阅collections.defaultdict的文档。

修改
我忘了这个__missing__功能被添加到python 2.5中的标准dict类中。因此,更简单的方法甚至不涉及collections.defaultdict - 只是子类dict

class my_defaultdict(dict):
    def __missing__(self, key):
        return '<unknown %s>' % key

答案 1 :(得分:1)

我认为您希望描述字典仅包含格式字符串,例如:

descriptions = {
   'player_joined_clan': "%(player)s joined clan %(clan)s.",
   #etc...
  }

然后你有一个函数接收一个描述键和一个特定于事件的数据字典,它会产生格式化的消息,如:

def getMessage( key, eventDataDict ):
  return descriptions[key] % eventDataDict

事实上,我认为您编写示例的方式token1等将在descriptions声明时进行评估 - 当我假设您想要的是在不同时间为这些变量的不同值格式化的消息。

答案 2 :(得分:1)

认为你要做的是添加另一个层,根据各种字典键的存在与否来选择格式化程序。

所以你可以使用像

这样的东西
formatters = {
    set('player', 'team'): "{player} joined {team}".format,
    set('player'): "Hello {player}.".format,
    set('team'): "{team} FTW!".format,
    set(): "Something happened.".format}

确定将使用哪个格式字符串。请注意,我使用的是与str.format配合使用的new-style format strings,而不是旧式的template % data。他们被推荐使用较旧的fmt = descriptions[set(eventDataDict.keys())] 个。

然后获得格式化功能

formatted_greeting = fmt(eventDataDict)

然后致电

default

这不如案例陈述,因为没有descriptions个案;如果您需要,可以在try ... except KeyError构造中包含format_description的访问权限,可能所有内容都在例如dict。您可能希望子类化{{1}}并将其作为该类的方法,具体取决于代码的结构。