内置容器的自定义比较 [英] custom comparison for built-in containers

查看:136
本文介绍了内置容器的自定义比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,有许多比较各种容器(list,dict等)的相等性。容器的键和值的类型为float,bool,int和str。内置的==和!=工作完美。

In my code there's numerous comparisons for equality of various containers (list, dict, etc.). The keys and values of the containers are of types float, bool, int, and str. The built-in == and != worked perfectly fine.

我刚刚了解到,在容器的值中使用的浮点数必须使用自定义比较函数进行比较。我已经写了这个函数(让我们称之为approxEqual(),并假设它需要两个浮点数,如果他们被判断为相等则返回True,否则返回False。)

I just learned that the floats used in the values of the containers must be compared using a custom comparison function. I've written that function already (let's call it approxEqual(), and assume that it takes two floats and return True if they are judged to be equal and False otherwise).

我希望对现有代码的更改保持最小。 (新类/函数/等可以根据需要复杂)

I prefer that the changes to the existing code are kept to a minimum. (New classes/functions/etc can be as complicated as necessary.)

示例:

if dict1 != dict2:
  raise DataMismatch

c $ c> dict1!= dict2 条件需要重写,以便使用approxEqual函数而不是 __ eq __

The dict1 != dict2 condition needs to be rewritten so that any floats used in values of dict1 and dict2 are compared using approxEqual function instead of __eq__.

字典的实际内容来自各种来源(解析文件,计算等)。

The actual contents of dictionaries comes from various sources (parsing files, calculations, etc.).

注意:我先提出问题了解如何覆盖内置float的 eq 。这本来是一个简单的解决方案,但我知道Python不允许覆盖内置类型的 __ eq __ 运算符。因此,这个新问题。

Note: I asked a question earlier about how to override built-in float's eq. That would have been an easy solution, but I learned that Python doesn't allow overriding built-in types' __eq__ operator. Hence this new question.

推荐答案

改变内置容器检查等式的唯一途径是使它们包含值,而不是原始,包装在覆盖 __ eq __ __ ne __ )。这是如果你需要改变容器本身使用等式检查的方式,例如。为运算符(其中右侧操作数是列表)以及容器方法(例如它们自己的 __ eq__ ( type(x).__ eq __(y)是Python将内部执行的代码的典型方法 x = = y )。

The only route to altering the way built-in containers check equality is to make them contain as values, instead of the "originals", wrapped values (wrapped in a class that overrides __eq__ and __ne__). This is if you need to alter the way the containers themselves use equality checking, e.g. for the purpose of the in operator where the right-hand side operand is a list -- as well as in containers' method such as their own __eq__ (type(x).__eq__(y) is the typical way Python will perform internally what you code as x == y).

如果你所说的是执行没有改变容器本身内部执行的检查),则唯一的方法是将每个 cont1 == cont2 改成(eg) same(cont1,cont2,value_same)其中 value_same 是接受两个值并返回 True == False 这可能是太具侵略性的WRT您指定的标准。

If what you're talking about is performing your own equality checks (without altering the checks performed internally by the containers themselves), then the only way is to change every cont1 == cont2 into (e.g.) same(cont1, cont2, value_same) where value_same is a function accepting two values and returning True or False like == would. That's probably too invasive WRT the criterion you specify.

如果您可以更改容器本身(即容器对象的位置数created比两个容器被检查是否相等的地方小得多),那么使用覆盖 __ eq __ 的容器子类是最好的。

If you can change the container themselves (i.e., the number of places where container objects are created is much smaller than the number of places where two containers are checked for equality), then using a container subclass which overrides __eq__ is best.

例如:

class EqMixin(object):
  def __eq__(self, other):
    return same(cont1, cont2, value_same)

> same 正如我在第二段中提到的)和

(with same being as I mentioned in the A's 2nd paragraph) and

class EqM_list(EqMixin, list): pass

(你需要的其他容器类型等等) )

(and so forth for other container types you need), then wherever you have (e.g.)

x = list(someiter)

将其更改为

x = EqM_list(someiter)

,并确保还捕获其他方法来创建列表对象,例如替换

and be sure to also catch other ways to create list objects, e.g. replace

x = [bah*2 for bah in buh]

x = EqM_list(bah*2 for bah in buh)

x = d.keys()

x = EqM_list(d.iterkeys())


b $ b

等等。

and so forth.

是的,我知道,什么麻烦 - 但它是Python的核心原则类型(无论是容器还是值类型,例如 float )本身不能更改。这是一个非常不同的哲学。 Ruby和Javascript(我个人更喜欢它,但我确实看到它有时看起来有限制。)

Yeah, I know, what a bother -- but it's a core principle (and practice;-) of Python that builtin types (be they containers, or value types like e.g. float) themselves cannot be changed. That's a very different philosophy from e.g. Ruby's and Javascript's (and I personally prefer it but I do see how it can seem limiting at times!).

编辑请求似乎是(在这个答案)如何实现相同对于各种容器类型,而不是如何应用它,而不改变 == 转换成函数调用。如果这是正确的,那么(eg)不使用迭代器为简单:

Edit: the OP specific request seems to be (in terms of this answer) "how do I implement same" for the various container types, not how to apply it without changing the == into a function call. If that's correct, then (e.g) without using iterators for simplicity:

def samelist(a, b, samevalue):
    if len(a) != len(b): return False
    return all(samevalue(x, y) for x, y in zip(a, b))

def samedict(a, b, samevalue):
    if set(a) != set(b): return False
    return all(samevalue(a[x], b[x]) for x in a))

请注意,这适用于 > NOT 。 模糊化一个dict的键(或一个集合的成员)的相等比较是一个 REAL 问题。首先,如何保证绝对确定 samevalue(a,b)和samevalue(b,c)隐含并确保 samevalue(a,c)?这个传递性条件不适用于我看过的大多数半敏感的模糊比较,但它对于基于哈希表的容器(如dicts和sets)是完全不可缺少的。如果你通过了这个障碍,那么使散列值以某种方式神奇地一致的噩梦 - 如果两个实际上不同的键在这个意义上映射到相等的相同键在其他的字典,两个相应的值应该使用那么...?这样疯狂就在于,如果你问我,所以我希望当你说的意思是,确切,键! - )

Note that this applies to values, as requested, NOT to keys. "Fuzzying up" the equality comparison of a dict's keys (or a set's members) is a REAL problem. Look at it this way: first, how to you guarantee with absolute certainty that samevalue(a, b) and samevalue(b, c) totally implies and ensures samevalue(a, c)? This transitivity condition does not apply to most semi-sensible "fuzzy comparisons" I've ever seen, and yet it's completely indispensable for the hash-table based containers (such as dicts and sets). If you pass that hurdle, then the nightmare of making the hash values somehow "magically" consistent arises -- and what if two actually different keys in one dict "map to" equality in this sense with the same key in the other dict, which of the two corresponding values should be used then...? This way madness lies, if you ask me, so I hope that when you say values you do mean, exactly, values, and not keys!-)

这篇关于内置容器的自定义比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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