如何重构这段Python代码以提高效率

1 投票
7 回答
512 浏览
提问于 2025-04-15 17:12

这个代码块可以正常工作,它会遍历一个文件,这个文件里有重复的数据组,然后提取出每组中的5个信息。

不过,我知道现在的处理方式不是最有效的,因为它会对每一行找到的每个键都进行循环。

我在想有没有一些Python高手能提供更有效的方法来做这件事。

def parse_params(num_of_params,lines):

  for line in lines:
    for p in range(1,num_of_params + 1,1):
      nam = "model.paramName "+str(p)+" "
      par = "model.paramValue "+str(p)+" "
      opt = "model.optimizeParam "+str(p)+" "
      low = "model.paramLowerBound "+str(p)+" "
      upp = "model.paramUpperBound "+str(p)+" "
      keys = [nam,par,opt,low,upp]
      for key in keys:
        if key in line:
          a,val = line.split(key)
          if key == nam: names.append(val.rstrip())
          if key == par: params.append(val.rstrip())
          if key == opt: optimize.append(val.rstrip())
          if key == upp: upper.append(val.rstrip())
          if key == low: lower.append(val.rstrip())

print "Names   = ",names   
print "Params   = ",params
print "Optimize = ",optimize
print "Upper    = ",upper
print "Lower    = ",lower

7 个回答

1

你确定 parse_params 是瓶颈吗?你有没有对你的应用进行性能分析?

import re
from collections import defaultdict 

names = ("paramName paramValue optimizeParam "
         "paramLowerBound paramUpperBound".split())
stmt_regex = re.compile(r'model\.(%s)\s+(\d+)\s+(.*)' % '|'.join(names))

def parse_params(num_of_params, lines):
    stmts = defaultdict(list)
    for m in (stmt_regex.match(s) for s in lines):
        if m and 1 <= int(m.group(2)) <= num_of_params: 
           stmts[m.group(1)].append(m.group(3).rstrip())

    for k, v in stmts.iteritems():
        print "%s = %s" % (k, ' '.join(v))
1

这里有很多重复的内容,如果你以后再添加一个 keyparam,你就得在很多地方都添加,这样很容易出错。你应该尽量减少这些重复的地方,使用某种数据模型,比如 dict(字典)。

其他人已经提供了一些很好的例子,所以我就简单说一下,让你有点思考的空间。

2

虽然这并没有直接回答你的问题(其他回答已经在讨论这个),但我想分享一个对我帮助很大的东西,那就是列表推导式。它们可以让你用一种简洁且我认为容易理解的方式来构建列表。

举个例子,下面的代码可以创建一个二维数组,里面包含你想要的值。如果我是这样做的话,some_funct会是一个小的正则表达式,它利用键中最后一个空格的索引作为参数,然后向前查找,收集你想在这一行中获取的值(这个值对应于当前查看的键),并把它添加到已经看到的键的二维数组的正确位置。

说得有点复杂,但如果你理解了列表推导式,并且能够构建出那个正则表达式,那么你就能得到一个简洁而有效的解决方案。

keys = ["model.paramName ","model.paramValue ","model.optimizeParam ""model.paramLowerBound ","model.paramUpperBound "]
for line in lines:
    seen_keys = [[],[],[],[],[]]
    [seen_keys[keys.index(k)].some_funct(line.index(k) for k in keys if k in line]

撰写回答