Python 减少函数调用

Python 减少函数调用,python,performance,Python,Performance,我分析了我的python程序,发现下面的函数运行时间太长。也许,我可以使用不同的算法,让它运行得更快。然而,我已经读到,我也可以通过减少函数调用来提高速度,特别是当它在循环中被重复调用时。我是一个python新手,我想学习如何做到这一点,看看它能快多少。目前,该功能是: def potentialActualBuyers(setOfPeople,theCar,price): count=0 for person in setOfPeople: if person.getUtilit

我分析了我的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
然而,这给了我一个错误,在赋值之前引用了
局部变量“person”
任何建议,如何减少函数调用或任何其他可以使代码更快的更改

同样,我是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))
返回自我效用[theCar]

*****编辑:寻求新的想法*****

有没有办法进一步加快速度。我用亚历克斯建议的方法把时间缩短了一半。我可以加快速度吗? 谢谢。

试试看(假设所有人都是同一类型的
):

此外,使用
is None
而不是
==None
应该稍微快一点。如果交换
术语有帮助,请尝试。

试一下(假设所有人都是同一类型的
):


此外,使用
is None
而不是
==None
应该稍微快一点。如果交换
术语有帮助,请尝试。

方法只是绑定到对象的函数:

    Utility = Person.getUtility
    for person in setOfPeople:
       if Utility(person, theCar) ...

但这并没有消除函数调用,而是消除了属性查找。

方法只是绑定到对象的函数:

    Utility = Person.getUtility
    for person in setOfPeople:
       if Utility(person, theCar) ...

不过,这并没有消除函数调用,而是消除了属性查找。

我怀疑,在这种情况下,通过提升对
person.getUtility的查找(按类,而不是按实例,正如其他实例所指出的那样),可以获得更高的速度。也许…:

return sum(1 for p in setOfPeople
           if p.periodCarPurchased is None
           and p.getUtility(theCar) >= price)

但我怀疑大部分时间实际上都花在执行
getUtility
(可能在查找
p.periodCarPurchased
时,如果这是一个与普通旧属性相反的奇特属性——我将后者移到了
之前,以防它是一个普通属性,并且可以保存大量的
getUtility
调用)。您的分析表明,与所讨论的方法(以及可能的属性)相比,在这个函数中花费的时间(扣除对其他函数的调用)占了多少?

我怀疑,在这种情况下,通过提升对
person.getUtility的查找,您可以获得多大的加速(按类,而不是按实例,正如其他实例所指出的那样).也许…:

return sum(1 for p in setOfPeople
           if p.periodCarPurchased is None
           and p.getUtility(theCar) >= price)

但我怀疑大部分时间实际上都花在执行
getUtility
(可能在查找
p.periodCarPurchased
时,如果这是一个与普通旧属性相反的奇特属性——我将后者移到了
之前,以防它是一个普通属性,并且可以保存大量的
getUtility
调用)。您的分析表明,与所讨论的方法(以及可能的属性)相比,花在这个函数上的时间(扣除对其他函数的调用)占了多少?

这一行让我的眼睛流血了:

   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)
Hmmm:3次查找
math.pow
和3次函数调用。幂有三种选择:
x**y
,内置的
pow(x,y[,z])
,和
math.pow(x,y)
。除非你有充分的理由使用其中一种,否则它是最好的(IMHO)要选择
x**y
,请保存属性查找和函数调用

self.utility[theCar] = self.A * theCar.mpg ** self.alpha * theCar.hp ** self.beta * theCar.pc ** self.gamma
annnnnnd在这里,让我们去掉水平滚动条:

self.utility[theCar] = (self.A
    * theCar.mpg ** self.alpha
    * theCar.hp  ** self.beta
    * theCar.pc  ** self.gamma)

一种可能需要对现有代码进行大量重写,而且可能不会有任何帮助(在Python中),那就是通过到处记录日志并使用
log\u utility=log\u A+log\u mpg*alpha…

这一行让我的眼睛流血:

   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)
Hmmm:3次查找
math.pow
和3次函数调用。幂有三种选择:
x**y
,内置的
pow(x,y[,z])
,和
math.pow(x,y)
。除非你有充分的理由使用其中一种,否则它是最好的(IMHO)要选择
x**y
,请保存属性查找和函数调用

self.utility[theCar] = self.A * theCar.mpg ** self.alpha * theCar.hp ** self.beta * theCar.pc ** self.gamma
annnnnnd在这里,让我们去掉水平滚动条:

self.utility[theCar] = (self.A
    * theCar.mpg ** self.alpha
    * theCar.hp  ** self.beta
    * theCar.pc  ** self.gamma)

可能需要对现有代码进行大量重写,但可能不会有任何帮助(在Python中)这将是为了避免大部分的功耗计算,方法是在所有地方都使用日志,并使用
log\u utility=log\u A+log\u mpg*alpha…

该错误指的是在枚举器中分配person之前引用person。它应该在“for person in set of people:”之后另外,当你说它需要很长时间才能运行时,你如何量化它?它实际需要多长时间,你正在运行的集合有多大?过早的优化是所有问题的根源。预计算方法引用不太可能为你带来任何加速。查看
getUtility
内部可能会得出一些见解。你能我也怀疑
getUtility
的实际逻辑会超过函数调用的开销。在做任何不自然的事情之前,先看看
中有哪些选项