我有一个用类设置字典初始化的Python类,如下所示:
def __init__(self, settings):
self._settings = settings
设置字典包含50-100个不同的参数,这些参数在其他方法中使用相当多:
def MakeTea(self):
tea = Tea()
if self._settings['use_sugar']:
tea.sugar_spoons = self._settings['spoons_of_sugar']
return tea
我想知道的是将所有参数预加载到像这样的实例属性中是否有意义:
def __init__(self, settings):
self._use_sugar = settings['use_sugar']
self._spoons_of_sugar = settings['spoons_of_sugar']
并使用这些属性,而不是每次需要时查找字典值:
def MakeTea(self):
tea = Tea()
if self._use_sugar:
tea.sugar_spoons = _self._spoons_of_sugar
return tea
现在,我对Python很陌生,而且我主要使用编译语言,而且它真的很简单:访问实例字段比从任何类型的基于哈希表的结构中查找值要快得多。但是,由于Python被解释,所有,我不确定我会有任何显着的性能提升,因为目前我几乎不知道Python解释器是如何工作的。据我所知,在代码中使用属性名称可能涉及在解释环境中使用一些标识符的内部词典,所以我什么也得不到。
所以,问题是:从字典中提取值并将它们放在实例属性中是否有任何显着的性能优势?这样做还有其他好处或缺点吗?什么是好的做法?
我坚信这是一项工程决策而非过早优化。此外,我只是好奇并试图编写不错的Python代码,所以这个问题似乎对我来说是否真的需要这些毫秒。
答案 0 :(得分:3)
您将属性访问权限(self.setting
)与属性访问权限(self.settings
)与字典查找(settings['setting']
)进行比较。类实际上是作为字典实现的,因此问题减少到两个字典查找而不是一个。一次查找会更快。
复制初始化dict的方法比另一个答案更简单快捷:
class Foobar(object):
def __init__(self, init_dict):
self.__dict__.update(init_dict)
但是,出于优化目的,我不会这样做。这既是过早的优化(你不知道你有速度问题,或者你的瓶颈是什么)和微优化(制定O(n 2 )算法O(n)将使与从原始算法中删除O(1)字典查找有很大的不同。)
如果某个地方,您多次访问其中一个设置,只需创建一个本地引用,而不是用大量设置污染Foobar
个实例的命名空间。
这是两个需要考虑的合理设计,但出于性能原因,您不应选择其中一个。而不是任何一个,我可能会创建另一个对象:
class Settings(object):
def __init__(self, init_dict):
self.__dict__.update(init_dict)
class Foobar(object):
def __init__(self, init_dict):
self.settings = Settings(init_dict)
只是因为我认为self.settings.setting
比self.settings['setting']
更好,而且它仍然保持井井有条。
如果事先知道所有设置名称是什么,这对collections.namedtuple
很有用。
答案 1 :(得分:0)
如果你将它们放入实例属性中,那么你将查找你的实例字典......所以最后你会做同样的事情。所以没有真正的性能增益或损失。
示例:
>>> class Foobar(object):
def __init__(self, init_dict):
for arg in init_dict:
self.__setattr__(arg, init_dict[arg])
>>> foo = Foobar({'foobar': 'barfoo', 'shroobniz': 'foo'})
>>> print(foo.__dict__)
{'foobar': 'barfoo', 'shroobniz': 'foo'}
因此,如果python查找foo.__dict__
或foo._settings
并没有真正起作用。