gpt4 book ai didi

python - 在 Python 中创建类的开销 : Exact same code using class twice as slow as native DS?

转载 作者:太空狗 更新时间:2023-10-29 21:18:09 25 4
gpt4 key购买 nike

我使用所有列表函数在 Python 中创建了一个 Stack 类作为练习。例如,Stack.push() 就是 list.append(),Stack.pop() 就是 list.pop(),Stack.isEmpty() 就是 list == [ ]。

我正在使用我的 Stack 类来实现一个十进制到二进制的转换器,我注意到即使这两个函数完全等同于我的 Stack 类对 push()、pop() 和 isEmpty() 的包装,使用 Stack 类的实现比使用 Python 列表的实现慢两倍。

那是因为在 Python 中使用类总是有固有的开销吗?如果是这样,从技术上讲(“幕后”)开销来自哪里?最后,如果开销如此之大,除非绝对必要,否则最好不要使用类?

def dectobin1(num):
s = Stack()
while num > 0:
s.push(num % 2)
num = num // 2
binnum = ''
while not s.isEmpty():
binnum = binnum + str(s.pop())
return binnum

def dectobin2(num):
l = []
while num > 0:
l.append(num % 2)
num = num // 2
binnum = ''
while not l == []:
binnum = binnum + str(l.pop())
return binnum


t1 = Timer('dectobin1(255)', 'from __main__ import dectobin1')
print(t1.timeit(number = 1000))

0.0211110115051

t2 = Timer('dectobin2(255)', 'from __main__ import dectobin2')
print(t2.timeit(number = 1000))

0.0094211101532

最佳答案

首先,警告:函数调用很少会限制您的速度。这通常是不必要的微优化。只这样做,如果它实际上限制了你的表现。之前做一些好的分析,看看是否有更好的优化方法。

确保您不会因为这个微小的性能调整而牺牲易读性!

Python 中的类有点像 hack。

它的工作方式是每个对象都有一个 __dict__ 字段(字典),其中包含该对象包含的所有属性。此外,每个对象都有一个 __class__ 对象,它又包含一个 __dict__ 字段(又是一个字典),其中包含所有类属性。

例如,看看这个:

>>> class X(): # I know this is an old-style class declaration, but this causes far less clutter for this demonstration
... def y(self):
... pass
...
>>> x = X()
>>> x.__class__.__dict__
{'y': <function y at 0x6ffffe29938>, '__module__': '__main__', '__doc__': None}

如果您动态定义一个函数(所以不是在类声明中而是在对象创建之后),该函数不会转到 x.__class__.__dict__ 而是转到 x.__dict__

还有两个字典保存当前函数可访问的所有变量。 globals()locals() 包括所有全局和局部变量。

那么现在让我们说,你有一个 x 类的对象 X 具有函数 yz在类声明中声明,第二个函数 z 是动态定义的。假设对象 x 是在全局空间中定义的。此外,为了比较,有两个函数 flocal() 定义在局部空间,fglobal() 定义在全局空间。

现在我将展示调用这些函数中的每一个会发生什么:

flocal():
locals()["flocal"]()

fglobal():
locals()["fglobal"] -> not found
globals()["fglobal"]()

x.y():
locals()["x"] -> not found
globals()["x"].__dict__["y"] -> not found, because y is in class space
.__class__.__dict__["y"]()

x.z():
locals()["x"] -> not found
globals()["x"].__dict__["z"]() -> found in object dict, ignoring z() in class space

如您所见,类空间方法需要更多时间来查找,对象空间方法也很慢。最快的选择是本地函数。

但是您可以在不牺牲类(class)的情况下解决这个问题。比方说,x.y() 被调用了很多,需要优化。

class X():
def y(self):
pass

x = X()
for i in range(100000):
x.y() # slow

y = x.y # move the function lookup outside of loop
for i in range(100000):
y() # faster

对象的成员变量也会发生类似的事情。它们也比局部变量慢。如果您调用一个函数或使用一个对象中的成员变量,而该对象是另一个对象的成员变量,则效果也会增加。例如

a.b.c.d.e.f()

会慢一点,因为每个点都需要另一个字典查找。

官方 Python 性能指南建议避免在代码的性能关键部分出现点: https://wiki.python.org/moin/PythonSpeed/PerformanceTips

关于python - 在 Python 中创建类的开销 : Exact same code using class twice as slow as native DS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41781048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com