【问题标题】:attribute call speed VS method call Python属性调用速度 VS 方法调用 Python
【发布时间】:2016-08-23 20:04:45
【问题描述】:

您好,我有一个简单的问题,但我找不到我正在寻找的直接比较。

我的问题是:

调用属性会比调用 Python 中的方法更快吗?

我有一个游戏,我想检查一个玩家是否发现了一个星球。我可以打电话给:

def check_exploration(self, planet):
    return True if self.name in planet.explored_by else False

或检查属性:

self.game.player.logbook[planet.name].is_discovered == True

我问的原因是因为我想删除两种方法中的一种,但我不确定要走哪条路。

您可能已经注意到我在使用该属性时有很多调用,这是因为我的游戏设计。每个对象都链接回我的游戏对象。所以我可以通过转到游戏对象并“退回”到目标对象的位置来访问每个对象。这很乏味,但我发现它比在模块之间跳来跳去导致无休止的循环引用要简单得多。

感谢您的建议。

【问题讨论】:

  • return True if self.name in planet.explored_by else False 应该只是 return self.name in planet.explored_by
  • 对于您的用例,任何一种方式都足够快。出于性能原因选择其中一个是没有意义的。选择使代码看起来最好的样式。
  • 谢谢!只是我开始拥有非常大的方法,其中包含一些我想重用的部分。这就是为什么我正在考虑将事情分解一下。 @wim 我不明白你的第一条评论...
  • 我的意思是True if x in y else False 等同于x in y

标签: python class optimization methods attributes


【解决方案1】:

我制作了一些脚本,可以生成银河系中行星的“planetsCount”,并检查“testsCount”次。 (邮件末尾的代码) 一些结果:

Preparing was done in 0.0 seconds, planetsCount is 10, testsCount is 1000000
First test time is 2.50099992752 sec
Second test time is 2.5 sec

Preparing was done in 0.0160000324249 seconds, planetsCount is 1000, testsCount is 1000000
First test time is 6.97200012207 sec
Second test time is 2.54799985886 sec

Preparing was done in 0.406000137329 seconds, planetsCount is 100000, testsCount is 10000
First test time is 6.09399986267 sec
Second test time is 0.0310001373291 sec

通过属性检查有稳定的时间。 在小列表上通过“列表中的项目”检查更快,但在大列表上非常慢。 代码如下

import random
import base64
import time

class Planet(object):
    def __init__(self, state, name):
        self.is_discovered = state
        self.name = base64.b64encode(name)

class Galaxy(object):
    planets = {}
    explored = []

    def __init__(self, planetCount):
        for planetIndex in xrange(planetCount):
            planetName = base64.b64encode(str(planetIndex))
            is_discovered = random.choice([True, False])
            planet = Planet(is_discovered, planetName)
            self.planets.update({planetName: planet})
            if is_discovered:
                self.explored.append(planetName)

startTime = time.time()
planetsCount = 10
testsCount = 1000000
galaxy = Galaxy(planetsCount)

print "Preparing was done in {} seconds, planetsCount is {}, testsCount is {}".format(time.time() - startTime, planetsCount, testsCount)

startTime = time.time()
for x in xrange(testsCount):
    planetName = base64.b64encode(str(random.randint(0, planetsCount - 1)))
    planetName in galaxy.explored
print "First test time is {} sec".format(time.time() - startTime)

startTime = time.time()
for x in xrange(testsCount):
    planetName = base64.b64encode(str(random.randint(0, planetsCount - 1)))
    galaxy.planets[planetName].is_discovered
print "Second test time is {} sec".format(time.time() - startTime)

【讨论】:

  • 谢谢。这很有用。因为我不希望达到 1000 颗行星标记。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 2012-10-24
  • 2018-10-16
  • 1970-01-01
  • 2016-09-04
  • 2015-12-03
相关资源
最近更新 更多