重写__eq__函数——对象list中使用in index()——获得list中不同属性对象个数
对于用list的元素为对象时,在使用in list和index()函数需要注意。
只实现__init__函数
class user:
def __init__(self,uid):
self.uid = uid
list1=[user(0),user(1),user(2)]
print( user(1) in list1 )
print( list1.index(user(1)) )
运行结果:
当判断一个对象是否在对象list中时,实际上,是在调用对象的__eq__函数,而默认的__eq__函数是在比较两个对象的存储地址,所以index函数会报错,报错信息为<__main__.user object at 0x0000000002E72518> is not in list
。
并且重写__eq__函数
class user:
def __init__(self,uid):
self.uid = uid
def __eq__(self,other):
if(type(self)==type(other)):
return self.uid==other.uid
else:
return False
list1=[user(0),user(1),user(2)]
print( user(1) in list1 )
print( list1.index(user(1)) )
运行结果:
发现,实现__eq__函数后,就覆盖掉了默认的__eq__函数了。且可以按照我们想要方式比较,即比较对象的成员的值,而不是比较对象的地址
优雅地重写__eq__函数
继续在百度搜了搜,没什么想要的,就去谷歌了,发现stackoverflow有一个类似问题,高票答案写得很好,网址在此Elegant ways to support equivalence (“equality”) in Python classes。
class Foo:
def __init__(self, item):
self.item = item
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
print(Foo(0) == Foo(0))#结果为True
重写__hash__函数(为了获得list拥有不同属性对象的个数)
class Foo:
def __init__(self, item):
self.item = item
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
def __hash__(self):
print('id',id(self))
return hash(id(self))
f1 = Foo(1)
f2 = Foo(1)
f3 = Foo(1)
print(set([f1, f2, f3]))
print(len(set([f1, f2, f3])))
运行结果:
可见,每个对象的id都不一样,而且每次创建集合时,都会调用一遍每个元素的hash函数。但这样写,还获得不到list拥有不同属性对象的个数,下面是正确的写法。
class Foo:
def __init__(self, item):
self.item = item
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
def __hash__(self):
"""Overrides the default implementation"""
return hash(tuple(sorted(self.__dict__.items())))
f1 = Foo(1)
f2 = Foo(1)
f3 = Foo(1)
print(f1.__dict__.items())
print(f1)
print(set([f1, f2, f3]))
print(len(set([f1, f2, f3])))
运行结果:
可见,当hash函数是如上写法时,具有相同属性的对象,就只会被加入集合中一次,因为他们的hash值是相同的。而且你可能会问,为什么不直接return hash(self.item)
,因为这样应付不了,当对象具有除了item以外的属性的这种情况。