Python class: 为什么我不能在 __eq__(self, other) 中使用 len() 方法?
Python class: Why can't I use the method len() inside __eq__(self, other)?
https://gist.github.com/rjurney/1e8454af8e44312d02d7
class FrozenSortedTuple:
"""A frozenset that cares about order of tuples. And is not actually frozen."""
def __init__(self, vals):
if type(vals) not in [list, set, tuple]:
raise Exception('Value not a list or set')
self.vals = list(vals)
def __eq__(self, other):
if len(self.vals) != len(other):
return False
if type(self.vals) != type(other):
return False
if type(other) not in [list, set, tuple]:
return False
other_list = list(other)
for i,item in enumerate(self.vals):
if item != other_list[i]:
return False
return True
在 iPython 调用:
In [2]: a = ['a','b']
In [3]: b = ['b','a']
In [4]: c = ['a','b']
In [5]: a == b
Out[5]: False
In [6]: FrozenSortedTuple(a)
Out[6]: <__main__.FrozenSortedTuple instance at 0x103c56200>
In [7]: fa = FrozenSortedTuple(a)
In [8]: fb = FrozenSortedTuple(b)
In [9]: fa == fb
错误:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-317181571e4d> in <module>()
----> 1 fa == fb
<ipython-input-1-ef99f0af5061> in __eq__(self, other)
15
16 def __eq__(self, other):
---> 17 if len(self.vals) != len(other):
18 return False
19 if type(self.vals) != type(other):
AttributeError: FrozenSortedTuple instance has no attribute '__len__'
我很困惑。
如果您尝试直接比较两个 FrozenSortedTuples 值的结构和内容,请将 other
的所有实例更改为 other.vals
。
def __eq__(self, other):
if len(self.vals) != len(other.vals):
return False
if type(self.vals) != type(other.vals):
return False
if type(other.vals) not in [list, set, tuple]:
return False
other_list = list(other.vals)
for i,item in enumerate(self.vals):
if item != other_list[i]:
return False
return True
当然,如果 other
不是 FrozenSortedTuple,这将无法工作。例如,fa == 23
将不起作用,因为数字 23 没有 "vals" 属性。
您定义 __eq__(self, other)
的方式,只有当 other 是您正在包装的类型(即列表、集合或元组)的实例时才能实现平等。您通过比较 FrozenSortedTuple
的两个实例来触发错误。错误消息告诉您无法在此类实例上调用 len(),那是因为您尚未在 class.
中定义方法 __len__(self)
如果您为 class 定义 __len__()
,它将起作用。请参阅 the Python Documentation(这链接到 2.7 文档,但它在 Python 3.x 中应该是一样的)
或者,您可以比较 len(self.vals) == len(other.vals)
来比较 FrozenSortedTuple
个实例。
谢谢,根据其他答案,我想要的是:
class FrozenSortedTuple:
"""A frozenset that cares about order of tuples. And is not actually frozen."""
def __init__(self, vals):
if type(vals) not in [list, set, tuple]:
raise Exception('Value not a list or set')
self.vals = vals
def __len__(self):
return len(self.vals)
def __iter__(self):
return iter(self.vals)
def __getitem__(self, key):
return list(self.vals)[key]
def __eq__(self, other):
if len(self) != len(other):
print "len(self)"
return False
for i,item in enumerate(self.vals):
if item != other[i]:
return False
return True
def __str__(self):
str_val = str()
for val in self:
str_val += str(val)
return str_val
def __hash__(self):
return hash(str(self))
测试:
# FrozenSortedTuple Tests
a = ['a','b']
b = ['b','a']
c = ['a','b']
fa = FrozenSortedTuple(a)
fb = FrozenSortedTuple(b)
fc = FrozenSortedTuple(c)
fa == fb
fa == fc
fa == ['a','b']
fa == ['b','a']
fa == ('a','b')
fa == ('b','a')
a = set([fa, fb, fc])
b = set([fa, fb, fc])
c = set([fa, fc, fb])
a == b
b == c
fa in a
fb in b
d = set([fb])
fa in d
https://gist.github.com/rjurney/1e8454af8e44312d02d7
class FrozenSortedTuple:
"""A frozenset that cares about order of tuples. And is not actually frozen."""
def __init__(self, vals):
if type(vals) not in [list, set, tuple]:
raise Exception('Value not a list or set')
self.vals = list(vals)
def __eq__(self, other):
if len(self.vals) != len(other):
return False
if type(self.vals) != type(other):
return False
if type(other) not in [list, set, tuple]:
return False
other_list = list(other)
for i,item in enumerate(self.vals):
if item != other_list[i]:
return False
return True
在 iPython 调用:
In [2]: a = ['a','b']
In [3]: b = ['b','a']
In [4]: c = ['a','b']
In [5]: a == b
Out[5]: False
In [6]: FrozenSortedTuple(a)
Out[6]: <__main__.FrozenSortedTuple instance at 0x103c56200>
In [7]: fa = FrozenSortedTuple(a)
In [8]: fb = FrozenSortedTuple(b)
In [9]: fa == fb
错误:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-317181571e4d> in <module>()
----> 1 fa == fb
<ipython-input-1-ef99f0af5061> in __eq__(self, other)
15
16 def __eq__(self, other):
---> 17 if len(self.vals) != len(other):
18 return False
19 if type(self.vals) != type(other):
AttributeError: FrozenSortedTuple instance has no attribute '__len__'
我很困惑。
如果您尝试直接比较两个 FrozenSortedTuples 值的结构和内容,请将 other
的所有实例更改为 other.vals
。
def __eq__(self, other):
if len(self.vals) != len(other.vals):
return False
if type(self.vals) != type(other.vals):
return False
if type(other.vals) not in [list, set, tuple]:
return False
other_list = list(other.vals)
for i,item in enumerate(self.vals):
if item != other_list[i]:
return False
return True
当然,如果 other
不是 FrozenSortedTuple,这将无法工作。例如,fa == 23
将不起作用,因为数字 23 没有 "vals" 属性。
您定义 __eq__(self, other)
的方式,只有当 other 是您正在包装的类型(即列表、集合或元组)的实例时才能实现平等。您通过比较 FrozenSortedTuple
的两个实例来触发错误。错误消息告诉您无法在此类实例上调用 len(),那是因为您尚未在 class.
__len__(self)
如果您为 class 定义 __len__()
,它将起作用。请参阅 the Python Documentation(这链接到 2.7 文档,但它在 Python 3.x 中应该是一样的)
或者,您可以比较 len(self.vals) == len(other.vals)
来比较 FrozenSortedTuple
个实例。
谢谢,根据其他答案,我想要的是:
class FrozenSortedTuple:
"""A frozenset that cares about order of tuples. And is not actually frozen."""
def __init__(self, vals):
if type(vals) not in [list, set, tuple]:
raise Exception('Value not a list or set')
self.vals = vals
def __len__(self):
return len(self.vals)
def __iter__(self):
return iter(self.vals)
def __getitem__(self, key):
return list(self.vals)[key]
def __eq__(self, other):
if len(self) != len(other):
print "len(self)"
return False
for i,item in enumerate(self.vals):
if item != other[i]:
return False
return True
def __str__(self):
str_val = str()
for val in self:
str_val += str(val)
return str_val
def __hash__(self):
return hash(str(self))
测试:
# FrozenSortedTuple Tests
a = ['a','b']
b = ['b','a']
c = ['a','b']
fa = FrozenSortedTuple(a)
fb = FrozenSortedTuple(b)
fc = FrozenSortedTuple(c)
fa == fb
fa == fc
fa == ['a','b']
fa == ['b','a']
fa == ('a','b')
fa == ('b','a')
a = set([fa, fb, fc])
b = set([fa, fb, fc])
c = set([fa, fc, fb])
a == b
b == c
fa in a
fb in b
d = set([fb])
fa in d