Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何比较python中自定义类中无对象的相等性?_Python_Class_Object_Comparison_Equals - Fatal编程技术网

如何比较python中自定义类中无对象的相等性?

如何比较python中自定义类中无对象的相等性?,python,class,object,comparison,equals,Python,Class,Object,Comparison,Equals,我正在为python编写一个队列数据结构,纯粹是为了学习。这是我的课程。当我比较两个Queue对象是否相等时,我得到了错误。我想会弹出错误,因为我不会在我的\uuuu eq\uuuu中比较None。但是我如何才能相应地检查None和return。事实上,我正在引擎盖下使用列表,并将其称为\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu >>> l=[1,2,3] >>

我正在为python编写一个
队列
数据结构,纯粹是为了学习。这是我的
课程
。当我比较两个
Queue
对象是否相等时,我得到了错误。我想会弹出错误,因为我不会在我的
\uuuu eq\uuuu
中比较
None
。但是我如何才能相应地检查
None
return
。事实上,我正在引擎盖下使用
列表
,并将其称为
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

>>> l=[1,2,3]
>>> l2=None
>>> l==l2
False
这是我的班级:

@functools.total_ordering
class Queue(Abstractstruc,Iterator):

    def __init__(self,value=[],**kwargs):
        objecttype = kwargs.get("objecttype",object)
        self.container=[]
        self.__klass=objecttype().__class__.__name__
        self.concat(value)


    def add(self, data):
        if (data.__class__.__name__==self.__klass or self.__klass=="object"): 
            self.container.append(data)
        else:
            raise Exception("wrong type being added")

    def __add__(self,other):
        return Queue(self.container + other.container)


    def __iadd__(self,other):
        for i in other.container:
            self.add(i)
        return self


    def  remove(self):
        return self.container.pop(0)


    def peek(self):
        return self.container[0]


    def __getitem__(self,index):
        return self.container[index]


    def __iter__(self):
        return Iterator(self.container)

    def concat(self,value):
        for i in value:
            self.add(i)

    def __bool__(self):
        return len(self.container)>0

    def __len__(self):
        return len(self.container)


    def __deepcopy__(self,memo):
        return Queue(copy.deepcopy(self.container,memo))

    def __lt__(self,other):
        return self.container.__lt__(other.container)

    def __eq__(self, other):
        return self.container.__eq__(other.container)
但当我尝试使用上述类进行比较时,我得到:

>>> from queue import Queue
>>> q = Queue([1,2,3])
>>> q
>>> print q
<Queue: [1, 2, 3]>
>>> q1 = None
>>> q==q1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "queue.py", line 65, in __eq__
    return self.container.__eq__(other.container)
AttributeError: 'NoneType' object has no attribute 'container'
>>> 
>>来自队列导入队列
>>>q=队列([1,2,3])
>>>q
>>>打印q
>>>q1=无
>>>q==q1
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“queue.py”,第65行,在__
返回自容器。\uuuueq\uuuuuu(其他容器)
AttributeError:“非类型”对象没有属性“容器”
>>> 

您的问题是如何实现
\uuuuueq\uuuuuu

请看以下代码:

q = Queue([1,2,3])
q1 = None
q==q1
让我们把它改写成等价的:

q = Queue([1,2,3])
q == None
现在,在
队列中。我们有:

def __eq__(self, other):
    return self.container.__eq__(other.container)
但是
other
None
,这意味着return语句正在调用:

self.container.__eq__(None.container)
正如你的错误正确指出的那样:

'NoneType' object has no attribute 'container'
因为它没有<代码>无
没有容器属性

因此,治疗方法取决于你想如何治疗它。现在,很明显,
队列
对象如果已定义,则不能是
,因此:

return other is not None and self.container.__eq__(other.container)
将延迟计算
other
是否为
None
,并在计算
后面的表达式部分之前返回
False
。否则,它将执行评估。但是,如果
其他
不是
队列
类型(或者更准确地说,其他对象没有
容器
属性),则会出现其他问题,例如:

q = Queue([1,2,3])
q == 1
>>> AttributeError: 'int' object has no attribute 'container'
所以。。。根据您的逻辑,如果
队列
不能与其他类型“相等”(这是只有您才能说的),您可以检查正确的类型,如下所示:

return other is not None and type(self) == type(other) and self.container.__eq__(other.container)
但是
None
NoneType
,因此它永远不能与
队列的类型相同。因此,我们可以再次将其缩短为:

return type(self) == type(other) and self.container.__eq__(other.container)
编辑:根据mglisons评论:

通过使用常规等式语句,可以使其更具python风格:

return type(self) == type(other) and self.container == other.container
他们还提出了一个很好的观点,即在检查可用性时使用
类型
。如果您确定
Queue
永远不会被子类化(这很难说明)。您可以使用异常处理来有效地捕获
AttributeError
,如下所示:

def __eq__(self, other):
    try:
        return self.container == other.container
    except AttributeError:
        return False    # There is no 'container' attribute, so can't be equal
    except:
        raise           # Another error occured, better pay it forward
以上可能被认为是有点过度设计,但从安全性和可恢复性的角度来看,这可能是更好的方法之一

或者使用
hasattr
的更好、更短的方法(我最初应该想到的)是:

return hasattr(other, 'container') and self.container == other.container

你可以这样做

    def __eq__(self,other):
        if other is None: return False
        return self.container.__eq__(other.container)
if not isinstance(other,Queue): return False
你可能还想做一些类似的事情

    def __eq__(self,other):
        if other is None: return False
        return self.container.__eq__(other.container)
if not isinstance(other,Queue): return False

告诉Python您不知道如何与其他类型进行比较:

def __eq__(self, other):
    if not isinstance(other, Queue):
        return NotImplemented
    return self.container.__eq__(other.container)

您可以考虑检查<代码> HasTART(其他,“容器”)<代码>,而不是<代码> iStase< /C> >,或者捕获<代码> AtditError < /代码>。 但重要的是,与其他答案建议的不同,当

other
不是队列时,您不希望
返回False
。如果返回
NotImplemented
,Python将给
other
一个检查相等性的机会;如果返回False,则不会返回。区分“这些物体是否相等”问题的三个可能答案:是、否,我不知道


您可能希望在
\uuult\uuu
中执行类似的操作,其中差异更为明显:如果您从
\ult\uuu
\uueq\uu
返回
False
,则由
总排序插入的
\ugt\uuuu
将返回True-即使您无法进行比较。如果您从这两个容器返回
NotImplemented
,它也将是
NotImplemented

为什么
self.container.\uu eq\uuu(…)
当您可以只执行
self.container==…
?另外,我不确定是否推荐
类型
相等。子类等呢?@mgilson我只是在重复使用OPs代码。您可以将其重写为
self.container==
。你让我用
类型检查了一下。你有什么建议?@legostrmtroopr--我想你可以试试
hasattr
,看看
other
是否有
container
属性并依赖duck键入。@user1988876--你的意思是
isinstance
?当然,你可以试试。e、 g.
返回isinstance(other,Queue)和self.container==other.container
@user1988876这在很大程度上取决于程序员的想法。如果一个
队列
只能等于其他
队列
s,而不能等于它们的子类,那么
类型(self)=类型(other)
是有效的。但这取决于你。这里有几种方法,尽管我在上面的评论中链接的问题建议不要使用
isinstance
和类似的方法。我不知道如何返回
NotImplemented
。我想这可能是个错误,你的意思是提出一个例外。。。不,没错: