封装会严重影响性能吗?

3 投票
8 回答
1360 浏览
提问于 2025-04-15 14:00

我知道这个问题可能有点傻,也许这只是写代码的一部分,但我发现定义简单的函数真的会严重影响性能……我做了一个简单的测试:

def make_legal_foo_string(x):
    return "This is a foo string: " + str(x)

def sum_up_to(x):
    return x*(x+1)/2

def foo(x):
    return [make_legal_foo_string(x),sum_up_to(x),x+1]

def bar(x):
    return ''.join([str(foo(x))," -- bar !! "])

这样写代码风格很好,让代码更清晰,但它的运行速度可能比直接写代码慢三倍。对于那些可能有副作用的函数,这种情况是不可避免的,但其实有些函数定义得几乎可以直接用代码行替代,每次出现时就直接用代码行替换掉,等到这样做后再编译代码。我觉得对于魔法数字也是一样,读取内存并不费时间,但如果这些数字不应该被改变,那为什么不在代码编译之前把每个“魔法”数字都替换成具体的数字呢?

8 个回答

2

封装主要是为了提高代码的可读性。如果你真的那么担心性能,以至于想要去掉封装的逻辑,那你不如直接用汇编语言来写代码。

封装还有助于调试和添加新功能。想象一下:假设你有一个简单的游戏,需要添加一些代码来在特定情况下减少玩家的生命值。这听起来很简单,对吧?

def DamagePlayer(dmg):
    player.health -= dmg;

这段代码确实很简单,所以很容易就想把“player.health -=”到处乱写。但是,如果你后来想要添加一个道具,让玩家在使用时受到的伤害减半呢?如果逻辑还保持封装,那就很简单了:

def DamagePlayer(dmg):
    if player.hasCoolPowerUp:
        player.health -= dmg / 2
    else
        player.health -= dmg

现在,假设你因为觉得这段逻辑太简单而没有进行封装。那你就得在50个不同的地方写同样的逻辑,至少有一个地方你几乎肯定会忘记,这样就会出现奇怪的bug,比如:“当玩家有道具时,所有伤害都减半,除了被外星羊攻击时……”

你想要和外星羊的问题吗?我想你不想。 :)

说正经的,我想表达的观点是,在合适的情况下,封装是非常有益的。当然,过度封装也很容易导致问题。此外,确实有一些情况下速度是非常重要的(虽然这种情况很少),那额外的几个时钟周期是值得的。找到合适的平衡,唯一的方法就是多加练习。不过,不要因为封装会稍微慢一点就拒绝它。通常来说,封装带来的好处远远超过它的成本。

2

我不太清楚Python的编译器有多厉害,但对于很多编程语言来说,编译器会通过“内联”来优化对小的过程、函数或方法的调用。其实在某些语言的实现中,自己去“微优化”代码反而可能会让性能变得更差。

6

函数调用的开销其实并不大;你通常不会注意到这些开销。你之所以在这种情况下能看到,是因为你的实际代码(x*x)实在是太简单了。在任何一个真正的程序中,进行函数调用所花费的时间几乎可以忽略不计。

(不过,我并不建议在这个例子中使用foo、identity和square;它们太简单了,直接写在一起更容易理解,而且并没有真正封装或抽象出什么东西。)

如果它们不应该被改变,那为什么不在代码编译之前就把每个'magic'替换成具体的值呢?

因为程序是为了让更容易阅读和维护的。你可以把常量替换成它们的具体值,但这样会让程序变得更难处理,而得到的好处微乎其微,可能你根本无法测量到:这就是所谓的过早优化

撰写回答