Python
2.x有两种方法可以重载比较运算符,__cmp__
也可以是“丰富的比较运算符”,例如__lt__
。
富比较重载据说是首选,但是为什么会这样呢?
丰富的比较运算符更易于实现,但是您必须使用几乎相同的逻辑来实现其中的多个运算符。但是,如果可以使用内建cmp
和元组排序,则将__cmp__
变得非常简单并完成所有比较:
class A(object):
def __init__(self, name, age, other):
self.name = name
self.age = age
self.other = other
def __cmp__(self, other):
assert isinstance(other, A) # assumption for this example
return cmp((self.name, self.age, self.other),
(other.name, other.age, other.other))
这种简单性似乎比重载所有丰富的6(!)比较更好地满足了我的需求。(但是,如果您依靠“交换参数” /反映的行为,则可以将其降低到“仅”
4,但根据我的拙见,这会导致并发症的净增加。)
如果我只是超载,是否需要注意任何无法预料的陷阱__cmp__
?
我明白了<
,<=
,==
等运营商也可以被重载用于其他目的,并且可以返回任何对象,他们喜欢。我并不是在问这种方法的优点,而只是在询问使用这些运算符进行比较时的区别,就如同它们对数字的含义一样。
更新: 正如Christopher指出的那样,cmp
它在3.x中消失了。
有没有其他选择可以像上面一样轻松实现比较__cmp__
?
是的,很容易__lt__
用mixin类(或元类,或者如果您以这种方式运行,则可以使用类装饰器)来实现所有内容。
例如:
class ComparableMixin:
def __eq__(self, other):
return not self<other and not other<self
def __ne__(self, other):
return self<other or other<self
def __gt__(self, other):
return other<self
def __ge__(self, other):
return not self<other
def __le__(self, other):
return not other<self
现在,您的类可以定义公正的对象,__lt__
并从ComparableMixin继承继承(在需要任何其他基础之后,如果有的话)。一个类装饰器将是非常相似的,只是插入与其装饰的新类的属性相似的函数(结果可能在运行时在微观上更快,而在内存方面的成本也同样小)。
当然,如果您的类有一些特别快的实现方式(例如__eq__
和)__ne__
,则应直接定义它们,以便不使用mixin的版本(例如的情况dict
)-实际上,__ne__
可以将其定义为方便作为:
def __ne__(self, other):
return not self == other
但是在上面的代码中,我想保持仅使用<
;-)的对称性。至于为什么__cmp__
要走,既然我们 确实
有__lt__
朋友,为什么还要用另一种不同的方法做完全一样的事情呢?在每个Python运行时(经典,Jython,IronPython,PyPy等)中,它是如此沉重。该代码
绝对 不会有虫子的是不存在的代码-
那里Python的原则是,应该是一个理想的执行任务明显的方式(C具有相同的原则的“C的精神”一节中ISO标准,顺便说一句)。
这并不意味着我们走的路,禁止的事情了(例如,混入以及一些应用类装饰之间近乎等价),但绝对 不
意味着我们不喜欢随身携带的编译器和代码/或冗余存在的运行时仅用于支持多种等效方法来执行完全相同的任务。
进一步的编辑:实际上,还有一种更好的方法可以为许多类提供比较和散列,包括问题中的那个-
一种__key__
方法,正如我在对该问题的评论中提到的那样。由于我从来没有为它编写PEP,因此,如果愿意,您当前必须使用Mixin(&c)来实现它:
class KeyedMixin:
def __lt__(self, other):
return self.__key__() < other.__key__()
# and so on for other comparators, as above, plus:
def __hash__(self):
return hash(self.__key__())
实例与其他实例的比较通常归结为比较每个元组和几个字段的情况,这是很常见的情况-
然后,散列应该在完全相同的基础上实现。的__key__
直接需要特殊的方法解决。
问题内容: 这是一个从来没有一个正确答案的问题,我已经在网上搜索了很多次,却找不到解决方案。 它适用于Firefox,Chrome。我的responseText将像Réunion这样返回char,它将显示为奇怪的符号。 我尝试了许多方法,例如编码和解码,在响应文件中设置标头都无效。我没主意了。请帮助某人。 在主文件中,确保设置了内容类型和字符集。 在您的AJAX加载页面中,确保您位于顶部。 问题解
问题内容: 问题 在解决这个问题之后,似乎基于文件或磁盘的实现可能是解决我在此处提到的问题的正确解决方案。精简版: 目前,我已将实施为。 条目以相当固定的速率连续添加到其中。稍后对此进行详细说明。 最终,无论如何,这意味着JVM耗尽了堆空间。 在工作中,(强烈)建议我使用SQLite解决此问题,但是在问了上一个问题之后,我认为数据库不是适合此工作的合适工具。所以- 让我知道这听起来是否疯狂 -我认
问题内容: 首先-我的描述;) 我从服务器收到XmlHttpRequests JSON响应。MySQL驱动程序将所有数据输出为字符串,PHP将其按原样返回,因此任何整数都将作为字符串返回,因此: JS中的parseInt()函数是否有任何快速替代方法(hack),可以解析纯数字字符串,例如 问题答案: 要转换为整数,只需使用一元+运算符,它应该是最快的方法: 可以通过类似的方式转换为其他类型: 更
问题内容: 我有以下内容: 和 终于我有了 如果我做 和P元帅,我只是把田野当作事物的一部分,而不是高度。 我知道我可以在A中添加@XmlSeeAlso(B.class),这一切都可以。 但是问题是我不知道B以外的所有扩展类,因为A可能在运行时扩展。 如何在运行时动态定义@XmlSeeAlso? 问题答案: 这取决于您如何创建JAXBContext。该newInstance方法可以与所有的类的显式
问题内容: 在一个Web项目中,用户上传了他们的文件,但是当我在服务器上收到它们时,它们将被存储为.tmp文件而不是原始文件扩展名(这也是我的首选行为)。 但是,这引起了问题。虽然对我来说本地的,但是在我的Linux开发机器上,它可以正常工作并且可以确定正确的mime类型,但是当我将项目上传到生产服务器(amazon beantalk)时,似乎无法正确确定mime类型。 从阅读javadocs来看
问题内容: 我正在尝试使用CSS和没有jquery动态地更改div的宽度。 以下代码将 我还希望支持IE 5.5及更高版本 ,我发现了以下内容:表达式。这是正确的用法吗? 我还可以支持Opera和Android浏览器吗? 问题答案: 几乎总是可以替换计算规则,例如用于布局。 例如: 如果我有以下标记: 而不是这样做:(假设边栏为300px宽) 做这个: PS: 我不会在IE 5.5(hahahah