为类启用比较

37 投票
4 回答
80427 浏览
提问于 2025-04-16 16:36

我需要一些帮助,关于我的计算机科学作业。这次作业是关于类和对象的,主要是定义一个圆的简单类,名字叫做 class Circle(object)。

作业的具体内容是这样的(我已经完成了前两部分,所以这第三部分是对最初问题的扩展):

"""扩展你的 Circle 类,使得可以使用比较运算符,比如 <, >, >=, <=, == 和 != 来比较 Circle 对象。如果一个圆的面积比另一个圆大,那么就认为它“更大”。

下面的代码:

A = Circle(2, 5, 1.5)
B = Circle(-6, 1, 1)
print A < B, A != B, A >= B

应该产生这样的输出:

False True True

这是我用来显示圆的坐标和半径的代码:

class Circle(object):
    def __init__(self, x=0, y=0, r=0):
        self.x = x
        self.y = y
        self.r = r
    def __str__(self):
        return "Circle at (%d , %d). Radius: %f" % (self.x, self.y, self.r)

def main():
    print Circle(3, 5, 4.0)

main()

这个类的输出是“Circle at (3 , 5). Radius: 4:000000”

老师给我们指了一本教科书的某一页,上面有关于类的数学运算符:eq()、gt()、ge()、lt()、le()、ne()等等。所以我在想,老师是不是想要这样的东西呢?

import math
class Circle(object):
    def __init__(self, x=0, y=0, r=0):
        self.x = x
        self.y = y
        self.r = r
    def __str__(self):
        return "Circle at (%d , %d). Radius: %f" % (self.x, self.y, self.r)
    def calcArea(self, r):
        self.r = r
        return (math.pi)*(r**2)
    def __gt__(self, circ1Radius, circ2Radius)
        self.circ1Radius = circ1Radius
        self.circ2Radius = circ2Radius
        r1 = circ1Radius
        r2 = circ2Radius
        r1 > r2 or r2 > r1
    def __ge__(self, circ1Radius, circ2Radius)
    #And so on for __lt__(), __le__(), __ne__(), etc
def main():
    A = Circle(3,4,1.5) 
    B = Circle(1,2,5.0)
    C = Circle(5,7,7) 
    D = Circle(9,8,3)
    print A < B, B > C, A < C, A >= C
main()
#Output should be "True, False, True, False"

我们是不是需要为每个想在类中使用的方法定义一个属性?谢谢大家的帮助。

4 个回答

0

这其实不是对你问题的直接回答,但要注意你的 calcArea(...) 方法其实不一定要放在这个类里面。(注意,它里面根本不需要用到 self!)

实际上,你可能想要的是一个仍然在类里面的方法,类似于

def area(self):
   return math.pi*(self.r**2)

这样的话,它就能真正使用你所在的圆的半径了。

48

你可以使用来自functools的total_ordering装饰器,这个装饰器可以根据你提供的__eq__()和其他一个比较方法,自动生成缺失的比较方法。

如果你有一个类定义了一个或多个丰富的比较排序方法,这个类装饰器会提供其余的方法。这可以简化你在指定所有可能的丰富比较操作时的工作量:

这个类必须定义以下之一:__lt__()(小于)、__le__()(小于等于)、__gt__()(大于)或__ge__()(大于等于)。另外,类还应该提供一个__eq__()方法(等于)。

例如,

import functools


@functools.total_ordering
class Student:
    def _is_valid_operand(self, other):
        return (hasattr(other, "lastname") and
                hasattr(other, "firstname"))

    def __eq__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))

    def __lt__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))
26

为这个类定义或重写比较运算符。 http://docs.python.org/reference/expressions.html#notin

看起来你走在正确的道路上,不过你只需要把第二个圆形对象传给你的比较方法。self指的是第一个圆形对象。所以self.r会给你第一个圆的半径。此外,你还需要从这个方法中返回True或False。

def __gt__(self, circle2):
    return self.r > circle2.r

注意,这里只是比较圆的半径。

撰写回答