0

我正在编写一个 Python 3 脚本,用于对林业木材数量进行制表。

工作人员会将他们标记的每棵树的树种、直径和高度通过无线电广播给计算机操作员。然后计算机操作员将输入如下命令:

OAK 14 2

这表示程序应该增加直径为 14 英寸、高度为两根原木的橡树的数量。

然而,工人们有时也一次调用不止一棵相同类型的树。所以程序也必须能够处理这个命令:

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 条目而不是增加它。如果省略第三个参数,则会引发 IndexError,并且处理程序会将其视为第三个参数为 1。

但是,如果我们同时处于这两种情况,就会出现问题。程序还没有听说过橡树,操作员也没有指定计数。KeyError 熄灭,但随后会生成自己的 IndexError,并且 Python 不喜欢在异常处理程序中发生异常时使用它。

我想最简单的方法是简单地删除一个或另一个 except 并以另一种方式完成其功能。不过,我想知道是否有更优雅的 Pythonic 方式来实现它。在那儿?

4

3 回答 3

0

最后,最好的方法是简单地删除 IndexError 处理程序,将 cmdtup 更改为列表,然后插入以下内容:

if len(cmdtup) >= 3:
    cmdtup.append(1)
于 2013-11-08T13:26:18.537 回答
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])

屈服

('OAK', 16, 1) = 2
('OAK', 14, 2) = 3

一些注意事项:

  • 这里没有错误处理,您应该处理应该是数字的值不是或输入以任何其他方式错误的情况
  • 而不是字符串,我使用元组作为字典索引
于 2013-11-02T21:36:27.950 回答
0

您可以使用,如果键不在字典中collections.Counter,则返回 0 而不是 a 。KeyError

计数器文件:

Counter对象有一个字典接口,除了它们为丢失的项目返回零计数而不是引发KeyError

像这样的东西:

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 的答案相同的注释适用。另一个好处Counter是,如果您想查看每周计数,您只需执行类似sum(daily_counts).

Counter如果您从命令列表开始,效果会更好:

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_counts上面的函数添加新树,或者您可以开始在另一个文本文件中收集命令,然后Counter为第二天、下周等生成第二个对象。

于 2013-11-03T05:51:39.370 回答