Python列表,查找对象名称,效率建议
假设我有一个这样的对象:
class Foo(object):
def __init__(self, name=None):
self.name = name
def __repr__(self):
return self.name
还有一个包含多个实例的列表,比如:
list = [Foo(name='alice'), Foo(name='bob'), Foo(name='charlie')]
如果我想找到一个特定名字的对象,我可以使用以下方法:
def get_by_name(name, list):
return [foo for foo in list if foo.name == name][-1]
这显然意味着:
print get_by_name('alice', list)
>> alice
不过,有没有更高效的数据结构或方法来获取这些对象呢?实际上,这些对象的名字只有在运行时才能知道,并且在对象的生命周期中可能会发生变化。
有什么建议吗?
更新:
感谢Matt Joiner的回答,我已经更新了代码,以支持多个同名的Foo对象:
class Foo(object):
_all_names = {}
def __init__(self, name=None):
self._name = None
self.name = name
@property
def name(self):
return self._name
@name.setter
def name(self, name):
if self._name is not None:
self._all_names[self._name].remove(self)
self._name = name
if name is not None:
self._all_names.setdefault(name, []).append(self)
@classmethod
def get_by_name(cls, name):
return cls._all_names[name]
def __repr__(self):
return "{0}".format(self.name)
l = [Foo("alice"), Foo("bob"), Foo('alice'), Foo('charlie')]
print Foo.get_by_name("alice")
print Foo.get_by_name("charlie")
对这种方法有什么看法吗?
2 个回答
1
这个情况有点让人困惑。
你要在一个列表中寻找这个对象,而列表是一种线性的数据结构。也就是说,你只能一个一个地查看,这样的话,所需的时间就会随着列表的长度线性增长。所以,这就是你速度慢的原因。
要提高速度,可以使用某种哈希方案,这样你就可以通过你感兴趣的键(在你的例子中是name
)直接找到对象。这就像在字典中查找键一样,查找的时间是固定的。这基本上就是Matt的回答所做的。他保持一个“索引”,作为类级别的结构,这样你就可以通过哈希查找,而不是一个一个地遍历列表。
8
试试这个:
class Foo(object):
_all_names = {}
def __init__(self, name=None):
self.name = name
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
self._all_names[name] = self
@classmethod
def get_by_name(cls, name):
return cls._all_names[name]
def __str__(self):
return "Foo({0})".format(self.name)
a = Foo("alice")
b = Foo("bob")
print Foo.get_by_name("alice")
请记住,这个例子很简单,主要是为了传达一个概念。其实你可以在这里做很多调整和检查。