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

发布于 2024-08-08 13:57:12 字数 589 浏览 8 评论 0原文

我必须在课堂上制作一个基本的 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 的方式一次读取一行并将状态转换为整数,同时将输入值保留为字符串。基本上这个想法是:

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 的方式来做到这一点。

I have to make a rudimentary FSM in a class, and am writing it in Python. The assignment requires we read the transitions for the machine from a text file. So for example, a FSM with 3 states, each of which have 2 possible transitions, with possible inputs 'a' and 'b', wolud have a text file that looks like this:

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

I am trying to come up with a more pythonic way to read a line at a time and convert the states to ints, while keeping the input vals as strings. Basically this is the idea:

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(" ")]

Of course, when it tries to int("a") it throws a ValueError. I know I could use a traditional loop and just catch the ValueError but I was hoping to have a more Pythonic way of doing this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

女皇必胜 2024-08-15 13:57: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]))

You should really only be trying to parse the tokens that you expect to be integers

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

Arguably more-readable:

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]))
小耗子 2024-08-15 13:57:12

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

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

This is something very functional, but I'm not sure if it's "pythonic"... And it may cause some people to scratch their heads. You should really have a "lazy" zip() to do it this way if you have a large number of values:

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())]

Also the arguments you use for strip and split can be omitted, because the defaults will work here.

Edit: reformatted - I wouldn't use it as one long line in real code.

暖树树初阳… 2024-08-15 13:57:12

您得到了非常适合您的问题的完美答案。但是,在其他情况下,确实可能存在这样的情况:如果可行(即,如果它们都是数字),您确实希望将某些字段转换为 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< /code> 输入类型的模式;但在更一般的情况下,您事先没有如此精确的信息,这可能是合适的!

You got excellent answers that match your problem well. However, in other cases, there may indeed be situations where you want to convert some fields to int if feasible (i.e. if they're all digits) and leave them as str otherwise (as the title of your question suggests) without knowing in advance which fields are ints and which ones are not.

The traditional Python approach is try/except...:

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

...which you need to wrap into a function as there's no way to do a try/except in an expression (e.g. in a list comprehension). So, you'd use it like:

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

However, it is possible to do this specific task inline, if you prefer:

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

the if/else "ternary operator" looks a bit strange, but one can get used to it;-); and the isdigit method of a string gives True if the string is nonempty and only has digits.

To repeat, this is not what you should do in your specific case, where you know the specific int-str-int pattern of input types; but it might be appropriate in a more general situation where you don't have such precise information in advance!

廻憶裏菂餘溫 2024-08-15 13:57:12
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,我想您也希望 finalStatesint

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

Note that you can shorten line.strip("\n").split(" ") down to just line.split(). The default behavior of str.split() is to split on any white space, and it will return a set of words that have no leading or trailing white space of any sort.

If you are converting the states to int in the loop, I presume you want the finalStates to be int as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文