我描述了我的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))
返回self.utility [theCar]
*****编辑:要求新想法*****
任何想法如何进一步提高速度。我用Alex建议的方法把时间缩短了一半。我可以进一步加快速度吗? 感谢。
答案 0 :(得分:2)
我怀疑你在这种情况下可以通过提升person.getUtility
的查找来获得更多的加速(按类,而不是实例,正如其他实例所指出的那样)。也许......
return sum(1 for p in setOfPeople
if p.periodCarPurchased is None
and p.getUtility(theCar) >= price)
但我怀疑大部分时间实际上是花在getUtility
的执行上(并且可能在p.periodCarPurchased
的查找中,如果这是一些奇特的属性而不是普通的旧属性 - 我搬了在and
之前的后者,以防它是一个普通属性并且可以保存一些getUtility
次调用)。你的分析是什么说这个函数花费的时间(扣除对其他人的调用)与所讨论的方法(可能是属性)相比?
答案 1 :(得分:1)
尝试改为(假设所有人都属于同一类型Person
):
Utility = Person.getUtility
for person in setOfPeople:
if Utility (person, theCar) >= ...
此外,使用== None
代替is None
的速度要快一些。如果交换and
条款有帮助,请尝试使用。
答案 2 :(得分:1)
方法只是绑定到对象的函数:
Utility = Person.getUtility
for person in setOfPeople:
if Utility(person, theCar) ...
但这并没有消除函数调用,它消除了属性查找。
答案 3 :(得分:1)
这一行使我的眼睛流血:
self.utility[theCar]=self.A*(math.pow(theCar.mpg,self.alpha))*(math.pow(theCar.hp,self.beta))*(math.pow(theCar.pc,self.gamma))
让它变得清晰易读,然后看看它是否更快。首先是一些空格:
self.utility[theCar] = self.A * (math.pow(theCar.mpg, self.alpha)) * (math.pow(theCar.hp, self.beta)) * (math.pow(theCar.pc, self.gamma))
现在我们可以看到有很多冗余的括号;删除它们:
self.utility[theCar] = self.A * math.pow(theCar.mpg, self.alpha) * math.pow(theCar.hp, self.beta) * math.pow(theCar.pc, self.gamma)
嗯:math.pow
和3次函数调用的3次查找。您有三种权力选择:x ** y
,内置pow(x, y[, z])
和math.pow(x, y)
。除非你有充分的理由使用其中一个,否则最好(恕我直言)选择x ** y
;保存属性查找和函数调用。
self.utility[theCar] = self.A * theCar.mpg ** self.alpha * theCar.hp ** self.beta * theCar.pc ** self.gamma
当我们在这里时,让我们摆脱水平滚动条:
self.utility[theCar] = (self.A
* theCar.mpg ** self.alpha
* theCar.hp ** self.beta
* theCar.pc ** self.gamma)
可能需要对现有代码进行相当重写,并且无论如何(在Python中)可能无法帮助,通过在任何地方记录日志并使用log_utility = log_A + log_mpg * alpha ...