1

我必须在课堂上制作一个基本的 FSM,并用 Python 编写它。作业要求我们从文本文件中读取机器的转换。例如,一个具有 3 个状态的 FSM,每个状态都有 2 个可能的转换,可能的输入“a”和“b”,会有一个如下所示的文本文件:

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 的方式来一次读取一行并将状态转换为整数,同时将输入 vals 保留为字符串。基本上是这样的想法:

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

4 回答 4

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]))
于 2009-10-20T20:37:19.943 回答
4

这是非常实用的东西,但我不确定它是否是“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 的参数也可以省略,因为默认值将在这里工作。

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

于 2009-10-20T20:38:03.530 回答
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的特定模式strint但在您事先没有如此精确的信息的更一般的情况下,这可能是合适的!

于 2009-10-21T01:44:49.150 回答
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

于 2009-10-20T23:03:33.757 回答