我正在研究python脚本来研究期权定价。我在XSL中做了很多预处理,并使用elementTree api输出一个读入我的python脚本的XML文件。
xml具有以下结构:
根XML节点的子节点是库存元素,每个库存一个
<stock>
元素的子元素是日元素,每天一个元素
<day>
元素的子元素是f元素,每个前进日都有一个元素
f元素有一些属性,“天”表示当天前进多远,“变化”表示当天股票价格的变化。
由于股票每天不交易,“@days”的顺序有差距。例如,与星期四关联的day元素可能如下所示:
<day [info in attributes>
<f days="1" change="-3.1"/>
<f days="4" change="-1"/>
<f days="5" change="0.4"/>
<f days="6" change="1.1"/>
...
</day>
现在,我正在尝试查找历史数据并查找@days = X的实例,其中X是输入。但是如果一个给定的<day>
元素没有这样的一天,我会选择一个f元素,其中@days = X - 1.如果它没有其中一个,我会寻找一个f元素@days = X + 1。
不幸的是,如果你没有使用天数= X的f元素,如果你试图做f [@days = X] .get('change'),elementTree库会抛出一个错误。所以我现在这样做了以下方式:
Changes = []
for day in Test_Stock:
forward_days = [int(f.get('days')) for f in day]
if X in forward_days:
expiry_day = [f for f in day if int(f.get('days')) == X]
Changes.append(float(expiry_day[0].get('change')))
elif (X - 1) in forward_days:
proxy_day = [f for f in day if int(f.get('days')) == (X - 1)]
Changes.append(float(proxy_day[0].get('change')))
elif (X + 1) in forward_days:
proxy_day = [f for f in day if int(f.get('days')) == (X + 1)]
Changes.append(float(proxy_day[0].get('change')))
这给出了预期的结果,但我希望有一种更简单的方法可以做到这一点,并希望知道如何更好地使用elementTree对象。
答案 0 :(得分:1)
因为X,X-1和X + 1的处理相同,所以可以使用如下循环:
Changes = []
for day in Test_Stock:
forward_days = [int(f.get('days')) for f in day]
for x in [X,X-1,X+1]:
if x in forward_days:
expiry_day = [f for f in day if int(f.get('days')) == x]
Changes.append(float(expiry_day[0].get('change')))
break
答案 1 :(得分:0)
而不是.get
,请使用.find
代替XPath,如果没有匹配的元素,则返回None
,而不是异常。
使用find
可让ElementTree
进行搜索,而无需手动过滤[f for f in int(f.get('days')) == x]
。
因此,对于每个day
,您想要的f
元素(如果存在)将是此列表中的第一个非None
项:
[day.find("f[@days='%d']" % index)
for index in [X, X - 1, X + 1]]
这也意味着你可以把你的整个功能写成像这样可怕的单行(未经测试):
Changes = [float(d[0].get('change'))
for d in [islice(ifilter(len, (day.find("f[@days='%d']" % candidate)
for candidate in [X, X - 1, X + 1])),
1)
for day in Test_Stock]
if d]
但请不要这样做。
然而,绝对要研究.find
。