在int()调用中,Python优雅失败?

时间:2009-10-20 20:30:26

标签: python fsm

我必须在一个类中创建一个基本的FSM,并用Python编写它。分配要求我们从文本文件中读取机器的过渡。例如,一个具有3个状态的FSM,每个状态有2个可能的转换,可能的输入'a'和'b',wolud有一个如下所示的文本文件:

2          # first line lists all final states
0 a 1
0 b 2
1 a 0
1 b 2
2 a 0
2 b 1

我试图想出一种更加pythonic的方式来一次读取一行并将状态转换为int,同时将输入值保持为字符串。基本上这就是这个想法:

self.finalStates = f.readline().strip("\n").split(" ")
for line in f:
  current_state, input_val, next_state = [int(x) for x in line.strip("\n").split(" ")]

当然,当它尝试int(“a”)时会抛出一个ValueError。我知道我可以使用传统的循环并捕获ValueError,但我希望有更多的Pythonic方法来实现这一点。

4 个答案:

答案 0 :(得分:12)

您应该只是尝试解析您希望为整数的标记

for line in f:
    tokens = line.split(" ")
    current_state, input_val, next_state = int(tokens[0]), tokens[1], int(tokens[2])

可以说是更具可读性:

for line in f:
    current_state, input_val, next_state = parseline(line)

def parseline(line):
    tokens = line.split(" ")
    return (int(tokens[0]), tokens[1], int(tokens[2]))

答案 1 :(得分:5)

这是非常实用的功能,但我不确定它是否是“pythonic”......而且它可能会让一些人挠头。如果你有大量的值,你应该有一个“懒惰”的zip()这样做:

types = [int, str, int]
for line in f:
   current_state, input_val, next_state = multi_type(types, line)

def multi_type(ts,xs): return [t(x) for (t,x) in zip(ts, xs.strip().split())]

此外,您可以省略用于strip和split的参数,因为默认值在此处可用。

编辑:重新格式化 - 我不会将它用作实际代码中的一条长行。

答案 2 :(得分:1)

你得到了很好的答案,可以很好地解决你的问题。但是,在其他情况下,可能确实存在这样的情况:如果可行(例如,如果它们都是数字),您希望将某些字段转换为int,否则将它们保留为str(作为标题你的问题建议)没有提前知道哪些字段是整数,哪些字段不是。

传统的Python方法是try / except ...:

def maybeint(s):
  try: return int(s)
  except ValueError: return s

...你需要将其包装到一个函数中,因为没有办法在表达式中进行try / except(例如在列表推导中)。所以,你可以使用它:

several_fields = [maybeint(x) for x in line.split()]

但是,如果您愿意, 可以内联执行此特定任务:

several_fields = [(int(x) if x.isdigit() else x) for x in line.split()]

if / else“三元运算符”看起来有点奇怪,但人们可以习惯它;-);如果字符串是非空的并且只有数字,则字符串的isdigit方法给出True。

重复一遍,这是您在特定情况下应该做些什么,您知道具体的int - str - int输入模式类型;但是在更普遍的情况下,你可能不适合提前获得如此准确的信息!

答案 3 :(得分:0)

self.finalStates = [int(state) for state in f.readline().split()]

for line in f:
    words = line.split()
    current_state, input_val, next_state = int(words[0]), words[1], int(words[2])
    # now do something with values

请注意,您可以将line.strip("\n").split(" ")缩短为line.split()str.split()的默认行为是在任何空格上拆分,它将返回一组没有任何前导或尾随空格的单词。

如果您要将状态转换为循环中的int,我认为您希望finalStates也是int