减少函数调用
我对我的Python程序进行了性能分析,发现下面这个函数运行得太慢了。也许我可以换个算法,让它跑得更快。不过,我听说通过减少函数调用次数也可能提高速度,特别是当这个函数在循环中被反复调用时。我是Python新手,想学习怎么做到这一点,看看能快多少。目前,这个函数是:
def potentialActualBuyers(setOfPeople,theCar,price):
count=0
for person in setOfPeople:
if person.getUtility(theCar) >= price and person.periodCarPurchased==None:
count += 1
return count
其中 setOfPeople
是一个包含 person
对象的列表。我尝试了以下方法:
def potentialActualBuyers(setOfPeople,theCar,price):
count=0
Utility=person.getUtility
for person in setOfPeople:
if Utility(theCar) >= price and person.periodCarPurchased==None:
count += 1
return count
但是,这样做给我报错,提示 local variable 'person' referenced before assignment
。有没有什么建议,可以减少函数调用或者其他能让代码更快的改动呢?
再次强调,我是Python新手,虽然我可能能用更好的算法,但学习如何减少函数调用还是很有意义的。
非常感谢。
***** 编辑 *****
添加了 getUtility
方法:
def getUtility(self,theCar):
if theCar in self.utility.keys():
return self.utility[theCar]
else:
self.utility[theCar]=self.A*(math.pow(theCar.mpg,self.alpha))*(math.pow(theCar.hp,self.beta))*(math.pow(theCar.pc,self.gamma))
return self.utility[theCar]
***** 编辑:寻求新想法 *****
有没有什么想法可以进一步加速这个过程?我用了Alex建议的方法,把时间缩短了一半。还能再快点吗?谢谢。
4 个回答
方法其实就是和一个对象绑定在一起的函数:
Utility = Person.getUtility
for person in setOfPeople:
if Utility(person, theCar) ...
不过,这并不意味着调用函数的过程被省略了,它只是省去了查找属性的步骤。
可以试试这个方法(假设所有的人都是同一种类型 Person
):
Utility = Person.getUtility
for person in setOfPeople:
if Utility (person, theCar) >= ...
另外,使用 is None
来判断是否为“没有值”会比 == None
稍微快一点。你可以试试换一下 and
的顺序,看是否有帮助。
我觉得在这种情况下,通过提前查找 person.getUtility
来提高速度的效果可能不大(是按类查找,而不是按实例查找,正如其他人提到的)。也许...:
return sum(1 for p in setOfPeople
if p.periodCarPurchased is None
and p.getUtility(theCar) >= price)
但我怀疑大部分时间其实是花在执行 getUtility
上(还有可能是在查找 p.periodCarPurchased
,如果它是个复杂的属性,而不是普通的属性的话——我把后者放在 and
前面,以防它真的是个普通属性,这样可以减少一些 getUtility
的调用次数)。你的性能分析结果显示这个函数(扣除它对其他函数的调用)花了多少时间,相比于这个方法(还有可能的属性)呢?