Python 如何更改实例(不在类中)的_cmp__函数?

Python 如何更改实例(不在类中)的_cmp__函数?,python,metaprogramming,cmp,Python,Metaprogramming,Cmp,如何更改实例(不在类中)的_cmp__函数 例: foo类: 定义初始化(self,num): self.num=num def cmp(自身、其他): 返回self.num-other.num #更改类工作中的cmp函数 foo.\uuuucmp\uuuuuu=cmp a=foo(1) b=foo(1) #返回True a==b #在实例中更改_cmp______)函数,这样做不起作用 def cmp2(自身、其他): 返回-1 a、 _u_cmp_uuu=cmp2 b、 _u_cmp_uuu

如何更改实例(不在类中)的_cmp__函数

例:

foo类:
定义初始化(self,num):
self.num=num
def cmp(自身、其他):
返回self.num-other.num
#更改类工作中的cmp函数
foo.\uuuucmp\uuuuuu=cmp
a=foo(1)
b=foo(1)
#返回True
a==b
#在实例中更改_cmp______)函数,这样做不起作用
def cmp2(自身、其他):
返回-1
a、 _u_cmp_uuu=cmp2
b、 _u_cmp_uuu=cmp2
#提出错误
a==b
#回溯(最近一次呼叫最后一次):
#文件“”,第1行,在
#TypeError:cmp2()正好接受2个参数(给定1个)
不要这样做 这将使您的代码出现错误,难以维护。它之所以困难,是因为正确的方法是将
foo子类化:

class FunkyCmpFoo( foo ):
    def __cmp__( self, other ):
        return -1
&c、 和c。这样,您就知道所有
foo
s都以相同的方式进行比较,而所有
FunkyCmpFoo
s都以相同的方式进行比较。如果你不这样做,你最终会将一个修改过的
foo
与一个原始的
foo
进行比较,而Cthulhu自己会从深处站起来惩罚你

我不确定是否应该这样说,但是,通过创建您自己的:


我可以想出这样做的一个很好的理由,那就是如果你的大敌必须调试代码。事实上,我可以想到一些非常有趣的事情来做(您希望
sys.maxint
如何比较小于所有偶数的数字?)。除此之外,这是一场噩梦。

编辑:如果在生产代码中这样做,我应该说你是一个坏人。你所有的头发和牙齿都会脱落,你将被诅咒在你的来世中永远走在这堆东西上

添加额外的间接寻址,这样就不会混淆绑定/未绑定方法:

class foo(object):
    def __init__(self, num):
        self.num = num
        self.comparer = self._cmp

    def __cmp__(self, other):
        return self.comparer(self, other)

    @staticmethod
    def _cmp(this, that):
        print 'in foo._cmp'
        return id(this) == id(that)

    def setcmp(self, f):
        self.comparer = f

def cmp2(self, other):
    print 'in cmp2'
    return -1

a = foo(1)
b = foo(1)

print a == b

a.setcmp(cmp2)
b.setcmp(cmp2)

print a == b

*您可以使用反多晶硅模式:

class foo(object):
    def __init__(self, num, i_am_special=None):
        self.num = num
        self.special = i_am_special

    def __cmp__(self, other):
        if self.special is not None:
            return -1
        else:
            return cmp(self.num, other.num)

    def __hash__(self):
        if self.special is not None:
            # TODO: figure out a non-insane value
            return 0
这会产生如下合理结果:

>>> a = foo(1)
>>> b = foo(2, 'hi mom')
>>> a > b
False
>>> b > a
False
>>> a == b
False
>>> b == b
False
我之所以发布这个答案,主要是因为我喜欢“反多晶硅”的发音。不要在家里这样做,孩子们没有适当的成人监督


[*未经许可使用的恐怖标志编码,或我确信是很棒的家伙的权利持有人,不需要像这样玷污他们的标志。]

虽然通常为类的不同实例更改比较函数是不好的做法,有时,您可能希望对要对其执行公共操作的一组实例使用不同的比较函数。例如,您希望根据不同的标准对它们进行排序

标准示例是
排序(列出\u foos,cmp=foocmp)
。尽管目前首选使用
参数,但实际上Python 3.x无论如何都不支持
cmp
参数(您可能希望使用
cmp\u to\u键


在这种情况下,最好的方法通常是使比较函数成为在实例组上操作的函数的参数,与排序后的
完全相同。

您的类应该继承自
对象
类foo(对象):
同一类(~类实例)的不同比较例程?为什么?+1只是因为引起了一些非常棒的答案=p你至少应该说不要那样做,否则实际上有人可能会=p谢谢!我不会在一个“真正的”代码,这只是为了好玩。
class foo(object):
    def __init__(self, num, i_am_special=None):
        self.num = num
        self.special = i_am_special

    def __cmp__(self, other):
        if self.special is not None:
            return -1
        else:
            return cmp(self.num, other.num)

    def __hash__(self):
        if self.special is not None:
            # TODO: figure out a non-insane value
            return 0
>>> a = foo(1)
>>> b = foo(2, 'hi mom')
>>> a > b
False
>>> b > a
False
>>> a == b
False
>>> b == b
False