Python 使用try…except处理变长命令元组
我正在编写一个Python3脚本,用于林业木材计数的制表 工人们将用无线电把他们标记的每棵树的种类、直径和高度发送给计算机操作员。然后,计算机操作员将输入如下命令:Python 使用try…except处理变长命令元组,python,python-3.x,exception-handling,Python,Python 3.x,Exception Handling,我正在编写一个Python3脚本,用于林业木材计数的制表 工人们将用无线电把他们标记的每棵树的种类、直径和高度发送给计算机操作员。然后,计算机操作员将输入如下命令: OAK 14 2 这意味着程序应该增加直径为14英寸、高度为2根原木的橡树数量 然而,工人们有时也会一次叫来不止一棵相同类型的树。因此,程序还必须能够处理此命令: OAK 16 1 2 这意味着我们要增加两个 因此,我设置解析器的方法是: key=cmdtup[0]+"_"+cmdtup[1]+"_"+cmdtup[2]
OAK 14 2
这意味着程序应该增加直径为14英寸、高度为2根原木的橡树数量
然而,工人们有时也会一次叫来不止一棵相同类型的树。因此,程序还必须能够处理此命令:
OAK 16 1 2
这意味着我们要增加两个
因此,我设置解析器的方法是:
key=cmdtup[0]+"_"+cmdtup[1]+"_"+cmdtup[2]
try:
trees[key]=int(trees[key])+int(cmdtup[3])
except KeyError:
trees[key]=int(cmdtup[3])
except IndexError:
trees[key]=int(trees[key])+1
如果程序被命令存储一个它以前没有存储过的树,一个KeyError将发生,处理程序将设置dict条目而不是增加它。如果省略了第三个参数,将引发一个索引器,处理程序会将其视为第三个参数为1
然而,如果我们同时处于两种情况,问题就会出现;程序还没有听说过橡树,操作员也没有指定计数。KeyError会关闭,但随后会生成自己的索引器,Python不喜欢在异常处理程序中发生异常时使用它
我想最简单的方法就是简单地删除其中一个,然后用另一种方式完成它的功能。不过,我想知道是否有一种更优雅、更像蟒蛇的方式。有吗?我会这样做:
def parse(cmd, trees):
res = cmd.split() # split the string by spaces, yielding a list of strings
if len(res) == 3: # if we got 3 parameters, set the fourth to 1
res.append(1)
for i in range(1,4): # convert parameters 1-3 to integers
res[i] = int(res[i])
key = tuple(res[x] for x in range(3)) # convert list to tuple, as lists cannot be dictionary indexes
trees[key] = trees.get(key,0) + res[3] # increase the number of entries, creating it if needed
trees={}
# test data
parse("OAK 14 2", trees)
parse("OAK 16 1 2", trees)
parse("OAK 14 2", trees)
parse("OAK 14 2", trees)
# print result
for tree in trees:
print(tree, "=", trees[tree])
from collections import Counter
counts = Counter()
def update_counts(counts, cmd):
cmd_list = cmd.split()
if len(cmd_list) == 3:
tree = tuple(cmd_list)
n = 1
else:
*tree, n = tuple(cmd_list)
counts[tree] += n
屈服
('OAK', 16, 1) = 2
('OAK', 14, 2) = 3
一些注意事项:
- 这里没有错误处理,您应该处理假定为数字的值不正确或输入以任何其他方式错误的情况
- 我使用元组作为字典索引,而不是字符串
集合。计数器,如果键不在字典中,它将返回0而不是键错误
计数器
对象有一个字典接口,除了它们为缺少的项返回零计数,而不是引发键错误
大概是这样的:
def parse(cmd, trees):
res = cmd.split() # split the string by spaces, yielding a list of strings
if len(res) == 3: # if we got 3 parameters, set the fourth to 1
res.append(1)
for i in range(1,4): # convert parameters 1-3 to integers
res[i] = int(res[i])
key = tuple(res[x] for x in range(3)) # convert list to tuple, as lists cannot be dictionary indexes
trees[key] = trees.get(key,0) + res[3] # increase the number of entries, creating it if needed
trees={}
# test data
parse("OAK 14 2", trees)
parse("OAK 16 1 2", trees)
parse("OAK 14 2", trees)
parse("OAK 14 2", trees)
# print result
for tree in trees:
print(tree, "=", trees[tree])
from collections import Counter
counts = Counter()
def update_counts(counts, cmd):
cmd_list = cmd.split()
if len(cmd_list) == 3:
tree = tuple(cmd_list)
n = 1
else:
*tree, n = tuple(cmd_list)
counts[tree] += n
与uselpa的答案中的注释相同。计数器的另一个优点是,如果您想查看每周计数,您只需执行类似于总和(每日计数)
的操作
计数器
如果从命令列表开始,效果会更好:
from collections import Counter
from itertools import repeat
raw_commands = get_commands() # perhaps read a file
command_lists = [c.split() for c in raw_commands]
counts = Counter(parse(command_lists))
def parse(commands):
for c in commands:
if len(c) == 3:
yield tuple(c)
elif len(c) == 4
yield from repeat(tuple(c[0:2]), times=c[3])
从那里,您可以使用上面的update\u counts
功能添加新树,或者您可以开始在另一个文本文件中收集命令,然后为第二天、第二周等生成第二个计数器对象。最后,最好的方法是删除索引器处理程序,将cmdtup更改为列表,并插入以下内容:
if len(cmdtup) >= 3:
cmdtup.append(1)
例如,不要欺负您的程序用户,强迫他们在cmd.exe中键入输入参数。那太残忍了。创建一些前端。argv无法使用它。在我发布的位上方有一个输入循环。另外,我还是最终用户。你能接受什么答案吗?@uselpa我发现我最终实现的解决方案是最好的,所以我自己回答了这个问题并接受了。