我在解析树时构建了大量高级对象列表。但是,在这一步之后,我必须从列表中删除重复项,并且我在Python 2中发现这个新步骤非常慢(它可以接受,但在Python 3中仍然有点慢)。但是我知道不同的对象实际上有一个不同的 id 。出于这个原因,我设法通过以下步骤获得更多更快的代码:
key=id
选项对列表进行排序; 因此,我有一个现在可以顺利运行的工作代码,但我想知道我是否可以在Python中更直接地完成这项任务。
示例。让我们构建两个具有相同值但具有不同 id 的相同对象(例如,我将按顺序执行fractions.Fraction
依赖标准库):
from fractions import Fraction
a = Fraction(1,3)
b = Fraction(1,3)
现在,如果我尝试通过使用pythonical list(set(...))
来实现我想做的事情,我会得到错误的结果,因为{a,b}
只保留两个值中的一个(相同但有不同的值) ID )。
我现在的问题是: id 删除重复内容的最快速,最可靠,最简短,最快捷的方法是什么,而不是 value 重复? 如果必须更改列表的顺序并不重要。
答案 0 :(得分:4)
您应该覆盖__eq__
方法,以便它取决于对象id
而不是其值。但请注意,您的对象也必须是可以清理的,因此您也应该定义一个正确的__hash__
方法。
class My_obj:
def __init__(self, val):
self.val = val
def __hash__(self):
return hash(self.val)
def __eq__(self, arg):
return id(self) == id(arg)
def __repr__(self):
return str(self.val)
演示:
a = My_obj(5)
b = My_obj(5)
print({a, b})
{5, 5}
答案 1 :(得分:3)
要小心,因为id
的描述可能会因某些基本类型而失败,其中python会在可能的情况下优化存储:
a = "foo"
b = "foo"
print(a is b)
产量
True
无论如何,如果你想处理标准对象(甚至是不可清洗的对象),你可以将它们存储在以id
为键的字典中。
分数示例:
from fractions import Fraction
a = Fraction(1,3)
b = Fraction(1,3)
d = dict()
d[id(a)] = a
d[id(b)] = b
print(d.values())
结果:
dict_values([Fraction(1, 3), Fraction(1, 3)])