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

发布于 2024-09-12 15:12:50 字数 592 浏览 10 评论 0原文

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

前任:

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

def cmp(self, other):
    return self.num - other.num

# Change __cmp__ function in class works
foo.__cmp__ = cmp
a = foo(1)
b = foo(1)

# returns True
a == b



# Change __cmp__ function in instance that way doesnt work
def cmp2(self, other):
    return -1

a.__cmp__ = cmp2
b.__cmp__ = cmp2

# Raise error 
a == b
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#TypeError: cmp2() takes exactly 2 arguments (1 given)

How can i change the __cmp__ function of an instance (not in class)?

Ex:

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

def cmp(self, other):
    return self.num - other.num

# Change __cmp__ function in class works
foo.__cmp__ = cmp
a = foo(1)
b = foo(1)

# returns True
a == b



# Change __cmp__ function in instance that way doesnt work
def cmp2(self, other):
    return -1

a.__cmp__ = cmp2
b.__cmp__ = cmp2

# Raise error 
a == b
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#TypeError: cmp2() takes exactly 2 arguments (1 given)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

愿得七秒忆 2024-09-19 15:12:50

不要这样做,

这会让你的代码充满错误并且难以维护。之所以困难,是因为正确的方法是子类化 foo

class FunkyCmpFoo( foo ):
    def __cmp__( self, other ):
        return -1

&c., &c.这样,您就知道所有 foo 都以相同的方式进行比较,并且所有 FunkyCmpFoo 都以相同的方式进行比较。如果您不这样做,您最终将把修改后的 foo 与原始 foo 进行比较,而克苏鲁本人将从深处升起来惩罚您。

我不确定是否应该这么说,但是这是可能的< /a>,通过创建您自己的 实例方法

funcType = type( foo.__cmp__ )
# Alternatively:
import new
cmp2 = new.instancemethod( func, a, foo )

a.__cmp__ = funcType( cmp2, a, foo )
b.__cmp__ = funcType( cmp2, b, foo )

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

DO NOT DO THIS

It will make your code buggy and hard to maintain. The reason it is difficult is because the right way to do it is to subclass foo:

class FunkyCmpFoo( foo ):
    def __cmp__( self, other ):
        return -1

&c., &c. This way, you know that all foos compare in the same way, and all FunkyCmpFoos compare in the same way. If you don't, you will eventually end up comparing a modified foo with an original foo, and Cthulhu himself will rise from the depths to punish you.

I'm not sure whether I should say this, but it is possible, by creating your own instance methods:

funcType = type( foo.__cmp__ )
# Alternatively:
import new
cmp2 = new.instancemethod( func, a, foo )

a.__cmp__ = funcType( cmp2, a, foo )
b.__cmp__ = funcType( cmp2, b, foo )

I can think of one good reason to do this, and that is if your archenemy has to debug the code. In fact, I can think of some quite fun things to do with that in mind (how would you like sys.maxint to compare less than all even numbers?). Apart from that, it's a nightmare.

缱倦旧时光 2024-09-19 15:12:50

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

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

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

Edit: This is the part where I'm supposed to say you're a bad person if you do this in production code. All your hair and teeth will fall out, and you'll be cursed to walk the stack forever during your afterlife.

Add an extra bit of indirection so you're not mixing up bound/unbound methods:

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
昵称有卵用 2024-09-19 15:12:50

alt text* 您可以使用反多态模式

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

我主要发布这个答案是因为我喜欢“反多态”的听起来。没有成人适当监督的孩子们,不要在家里这样做。

[* 编码恐怖徽标未经 Jeff Atwood 或权利持有者 Steven C. McConnell 我确信他是好人,不需要他们的标记像这样被玷污。]

alt text* You can use the anti-polymorphon pattern:

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

Which gives sensible results like:

>>> a = foo(1)
>>> b = foo(2, 'hi mom')
>>> a > b
False
>>> b > a
False
>>> a == b
False
>>> b == b
False

I mostly posted this answer because I liked how "anti-polymorphon" sounded. Don't do this at home, kids without proper adult supervision.

[* coding horror logo used without permission of Jeff Atwood or the rights holder Steven C. McConnell who I'm sure are swell guys and don't need their mark sullied like this.]

梦醒灬来后我 2024-09-19 15:12:50

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

标准示例为 sorted(list_of_foos, cmp = foocmp)。尽管目前首选使用 key 参数,而且事实上 Python 3.x 无论如何也不支持 cmp 参数(您需要使用 cmp_to_key )。

在这种情况下,最好的方法通常是使比较函数成为对实例组进行操作的函数的参数,就像 sorted 所做的那样。

While it is bad practice to change the comparison function for different instances of a class in general, sometimes you may want to use a different comparison function for a group of instances for which you want to do a common operation. An example is when you want to sort them according to different criteria.

The standard example would be sorted(list_of_foos, cmp = foocmp). Notwithstanding that it is currently preferred to use the key parameter and in fact Python 3.x doesn't support the cmp parameter anyway (you would want to use cmp_to_key).

In this case the best way is usually to make the comparison function a parameter of the function operating on the group of instances, exactly as sorted does.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文