为什么要保持基于身份的平等比较? [英] Why keep identity-based equality comparison?

查看:53
本文介绍了为什么要保持基于身份的平等比较?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,


Guido已经决定,在python-dev中,在Py3K中基于身份的订单

比较将被删除。这意味着,例如,{}< []"

将引发TypeError而不是当前行为,即

返回一个值,实际上是id({})< id([])。


他还说默认的平等比较将继续是基于身份的b $ b b。这意味着x == y永远不会引发异常,

就像现在的情况一样。这就是他的理由:

Hello,

Guido has decided, in python-dev, that in Py3K the id-based order
comparisons will be dropped. This means that, for example, "{} < []"
will raise a TypeError instead of the current behaviour, which is
returning a value which is, really, id({}) < id([]).

He also said that default equality comparison will continue to be
identity-based. This means that x == y will never raise an exception,
as is the situation is now. Here''s his reason:

让我构建一个假设的例子:假设我们代表汽车
及其部分作为对象。让我们说每个轮子都是一个物体。每个
轮都是独一无二的,我们没有相应的等级。
然而,构建轮组(例如当前在我车上的车轮组)会很有用。从来没有一个爆胎)。 Python
设置使用哈希就像dicts一样。原始的hash()和__eq__
实现可以完全正确地用于此目的,并且似乎很难将它添加到可能被用作集合成员的每个对象类型中。 (特别是因为这意味着如果第三个派对库为你创建了没有实现的对象__hash__
你将很难添加它。)
Let me construct a hypothetical example: suppose we represent a car
and its parts as objects. Let''s say each wheel is an object. Each
wheel is unique and we don''t have equivalency classes for them.
However, it would be useful to construct sets of wheels (e.g. the set
of wheels currently on my car that have never had a flat tire). Python
sets use hashing just like dicts. The original hash() and __eq__
implementation would work exactly right for this purpose, and it seems
silly to have to add it to every object type that could possibly be
used as a set member (especially since this means that if a third
party library creates objects for you that don''t implement __hash__
you''d have a hard time of adding it).




现在,我认为不应该如此。我的理由基本上是明确的是

比隐含的更好。 - 我认为应该保留==运算符

进行基于值的比较,并且如果两个对象

不能通过值进行有意义的比较则引发异常。如果你想检查两个

对象是否相同,你总是可以做x是y。如果你想根据他们的身份创建

a一组对象(也就是说,两个不同的具有相同值的
对象被认为是不同的元素),你就是

有两个选项:

1.创建另一个集合类型,它是基于身份的 - 它不关心

关于对象的哈希值,它只是收集对

对象的引用。而不是使用set(),你可以使用,比如说,

idset(),一切都可以正常工作。

2.写一个像这样的类:


class Ref(对象):

def __init __(self,obj):

self._obj = obj

def __call __(自我):

返回self._obj

def __eq __(自我,其他):

返回isinstance (其他,参考)和self._obj是other._obj

def __hash __(自我):

返回id(self._obj)^ 0xBEEF


并像这样使用它:


st = set()

st.add(Ref(wheel1))

st.add(Ref(wheel2))

如果参考(wheel1)在st:

....

那些解决方案允许编写类的人定义一个基于值的b $ b比较运算符,并允许类的用户明确说明他是否需要基于价值的行为或基于身份的行为

行为。


为什么这种明确的行为是好的: br />

*像十进制(3.0)== 3.0之类的东西会更有意义(提出一个

异常,这解释了小数不应该与

浮点数相比,而不是返回False)。

*你不可能使用对象作为键,期望它们按值进行比较,并且当它们不是时会导致错误。我最近编写了

a sort-of OCR程序,其中包含从numarray数组到b字符的映射到字符(数组是字符的像素图像) 。

一切似乎都有效,但程序没有识别任何

字符。我发现原因是阵列根据他们的身份进行了哈希处理,这是我必须猜测的事情。如果没有定义

默认==运算符,我会立即得到一个TypeError



*它更向前兼容 - 当它发现可以明智地比较两种类型

,可以定义比较,而不会改变现有的行为,而不会引发异常。


我的问题是,为Py3K留下当前默认的

等值运算符还有什么理由,不计算向后兼容性?

(假设你有idset和iddict,所以明确的''成本只是

两个字符,在Guido的例子中)


谢谢,

Noam



Now, I don''t think it should be so. My reason is basically "explicit is
better than implicit" - I think that the == operator should be reserved
for value-based comparison, and raise an exception if the two objects
can''t be meaningfully compared by value. If you want to check if two
objects are the same, you can always do "x is y". If you want to create
a set of objects based on their identity (that is, two different
objects with the same value are considered different elements), you
have two options:
1. Create another set type, which is identity-based - it doesn''t care
about the hash value of objects, it just collects references to
objects. Instead of using set(), you would be able to use, say,
idset(), and everything would work as wanted.
2. Write a class like this:

class Ref(object):
def __init__(self, obj):
self._obj = obj
def __call__(self):
return self._obj
def __eq__(self, other):
return isinstance(other, Ref) and self._obj is other._obj
def __hash__(self):
return id(self._obj) ^ 0xBEEF

and use it like this:

st = set()
st.add(Ref(wheel1))
st.add(Ref(wheel2))
if Ref(wheel1) in st:
....
Those solutions allow the one who writes the class to define a
value-based comparison operator, and allow the user of the class to
explicitly state if he wants value-based behaviour or identity-based
behaviour.

A few more examples of why this explicit behaviour is good:

* Things like "Decimal(3.0) == 3.0" will make more sense (raise an
exception which explains that decimals should not be compared to
floats, instead of returning False).
* You won''t be able to use objects as keys, expecting them to be
compared by value, and causing a bug when they don''t. I recently wrote
a sort-of OCR program, which contains a mapping from a numarray array
of bits to a character (the array is the pixel-image of the char).
Everything seemed to work, but the program didn''t recognize any
characters. I discovered that the reason was that arrays are hashed
according to their identity, which is a thing I had to guess. If
default == operator were not defined, I would simply get a TypeError
immediately.
* It is more forward compatible - when it is discovered that two types
can sensibly be compared, the comparison can be defined, without
changing an existing behaviour which doesn''t raise an exception.

My question is, what reasons are left for leaving the current default
equality operator for Py3K, not counting backwards-compatibility?
(assume that you have idset and iddict, so explicitness'' cost is only
two characters, in Guido''s example)

Thanks,
Noam

推荐答案

sp ******* @ gmail.com 写道:
我的问题是,留下当前默认的Py3K等值运算符的原因是什么,而不是计算向后兼容性?
(假设你有idset和iddict,所以显然''的成本只有两个字符,在Guido的例子中)
My question is, what reasons are left for leaving the current default
equality operator for Py3K, not counting backwards-compatibility?
(assume that you have idset and iddict, so explicitness'' cost is only
two characters, in Guido''s example)




是的。在异类容器中搜索项目。随着您的更改

到位,在...中运算符变得非常无价值

容器的异构对象。对于

的容器方法,同样搜索相等的容器方法也是如此。成员。每当你比较两个没有相同类型的对象时,你会得到一个例外并终止

搜索。如果你找到的对象会被找到

稍后,你输了 - 你会得到错误的答案。


你可以解决通过修补所有适当的方法。但是后来

你怎么描述他们的行为,而不是让一些人期望

如果他们传递了无与伦比的类型会引发异常?

此外,每个容器类型现在都具有身份和

之间的这种分割,必须为每个*容器类处理相等。如果你想对对象进行

身份比较,你必须将它们存储在idlist中

,以便in操作符和索引方法正常工作。

我也认为你的基本想法是错误的。表达式x == y表示x == y。如果x和y不可比,那么直观地是假的
。我会说打破那个

是一件坏事。但是,如果你不打破它,那么让x == y

引发用户类的异常似乎是错误的。比较应该是
,除非它们是同一个对象 - 这正是

基于id的平等给我们的。


< mike

-

Mike Meyer< mw*@mired.org> http://www.mired.org/home/mwm/

独立的WWW / Perforce / FreeBSD / Unix顾问,电子邮件以获取更多信息。



Yes. Searching for items in heterogenous containers. With your change
in place, the "in" operator becomes pretty much worthless on
containers of heterogenous objects. Ditto for container methods that
do searches for "equal" members. Whenever you compare two objects that
don''t have the same type, you''ll get an exception and terminate the
search. If the object your searching for would have been found
"later", you lose - you''ll get the wrong answer.

You could fix this by patching all the appropriate methods. But then
how do you describe their behavior, without making some people expect
that it will raise an exception if they pass it incomparable types?

Also, every container type now has this split between identity and
equality has to be dealt with for *every* container class. If you want
identity comparisons on objects, you have to store them in an idlist
for the in operator and index methods to work properly.

I also think your basic idea is wrong. The expression "x == y" is
intuitively False if x and y aren''t comparable. I''d say breaking that
is a bad thing. But if you don''t break that, then having "x == y"
raise an exception for user classes seems wrong. The comparison should
be False unless they are the same object - which is exactly what
equality based on id gives us.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.


Mike Meyer写道:
Mike Meyer wrote:
我的问题是,离开Py3K的当前默认
等值运算符还有什么理由,不计算向后兼容性?
(假设你有idset和iddict,所以显而易见''花费仅仅是两个角色,在Guido'的例子中)
My question is, what reasons are left for leaving the current default
equality operator for Py3K, not counting backwards-compatibility?
(assume that you have idset and iddict, so explicitness'' cost is only
two characters, in Guido''s example)



是的。在异类容器中搜索项目。随着您的变更
,在...中对于异质对象的容器,运算符变得毫无价值。同样用于搜索相等的容器方法。成员。每当你比较两个没有相同类型的对象时,你会得到一个例外并终止
搜索。如果你找到的对象会被发现
稍后,你输了 - 你会得到错误的答案。

你可以通过修补所有适当的方法来解决这个问题。但是那么你怎么描述他们的行为,而不是让一些人期望如果他们通过无比的类型会引发异常呢?

此外,每个容器类型现在都有身份和/或平等之间的这种分裂必须针对*每个*容器类来处理。如果你想对对象进行身份比较,你必须将它们存储在idlist中,以便in操作符和索引方法正常工作。

我也认为你的基本想法是错误。表达式x == y表示x == y。如果x和y不可比,那么直观地是假的。我会说打破那个
是件坏事。但是,如果你不打破它,那么让x == y
引发用户类的异常似乎是错误的。比较应该是假的,除非它们是同一个对象 - 这正是基于id给我们的平等。



Yes. Searching for items in heterogenous containers. With your change
in place, the "in" operator becomes pretty much worthless on
containers of heterogenous objects. Ditto for container methods that
do searches for "equal" members. Whenever you compare two objects that
don''t have the same type, you''ll get an exception and terminate the
search. If the object your searching for would have been found
"later", you lose - you''ll get the wrong answer.

You could fix this by patching all the appropriate methods. But then
how do you describe their behavior, without making some people expect
that it will raise an exception if they pass it incomparable types?

Also, every container type now has this split between identity and
equality has to be dealt with for *every* container class. If you want
identity comparisons on objects, you have to store them in an idlist
for the in operator and index methods to work properly.

I also think your basic idea is wrong. The expression "x == y" is
intuitively False if x and y aren''t comparable. I''d say breaking that
is a bad thing. But if you don''t break that, then having "x == y"
raise an exception for user classes seems wrong. The comparison should
be False unless they are the same object - which is exactly what
equality based on id gives us.




借调。如果Python不允许==异类

类型,



Seconded. All hell would break loose if Python didn''t allow == for heterogenous
types,


DEITY只知道我依赖它的类型,那么一切都会崩溃。请不要放弃它在Py3k中获得


-

Giovanni Bajo
DEITY only knows how many types I relied on it. Please don''t let it go
in Py3k.
--
Giovanni Bajo

这篇关于为什么要保持基于身份的平等比较?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆