使类支持比较操作

Posted jeffrey-yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使类支持比较操作相关的知识,希望对你有一定的参考价值。

Python的基础数据类型大多支持比较操作,如 >=, ==, <=等。类对象默认不支持对象间比较操作,除非实现相应的__le__, __eq__, __le__方法等。

Python类可以通过为每个比较运算符实现一个特殊的方法来支持比较。 例如,要支持>=运算符,请在类中定义__ge __()方法。 尽管定义单个方法通常没有问题,但是创建每个可能的比较运算符的实现很快变得很繁琐。

Python模块functools提供了total_ordering类装饰器方法,可用于简化此过程。 要使用它,可以用它装饰一个类,并定义__eq ()和另一个比较方法(lt le gt__或__ge__)。 然后,装饰器填充其他未实现的比较方法。如下:

from functools import total_ordering


class Room:
    def __init__(self, name, length, width):
        self.name = name
        self.length = length
        self.width = width
        self.square_feet = self.length * self.width


@total_ordering
class House:
    def __init__(self, name, style):
        self.name = name
        self.style = style
        self.rooms = list()

    @property
    def living_space_footage(self):
        return sum(r.square_feet for r in self.rooms)

    def add_room(self, room):
        self.rooms.append(room)

    def __str__(self):
        return '{}: {} square foot {}'.format(self.name, self.living_space_footage, self.style)

    def __eq__(self, other):
        return self.living_space_footage == other.living_space_footage

    def __lt__(self, other):
        return self.living_space_footage < other.living_space_footage


# Build a few houses, and add rooms to them
h1 = House('h1', 'Cape')
h1.add_room(Room('Master Bedroom', 14, 21))
h1.add_room(Room('Living Room', 18, 20))
h1.add_room(Room('Kitchen', 12, 16))
h1.add_room(Room('Office', 12, 12))

h2 = House('h2', 'Ranch')
h2.add_room(Room('Master Bedroom', 14, 21))
h2.add_room(Room('Living Room', 18, 20))
h2.add_room(Room('Kitchen', 12, 16))

h3 = House('h3', 'Split') 
h3.add_room(Room('Master Bedroom', 14, 21)) 
h3.add_room(Room('Living Room', 18, 20)) 
h3.add_room(Room('Office', 12, 16)) 
h3.add_room(Room('Kitchen', 15, 17))
houses = [h1, h2, h3]

print('Is h1 bigger than h2?', h1 > h2) # prints True
print('Is h2 smaller than h3?', h2 < h3) # prints True
print('Is h2 greater than or equal to h1?', h2 >= h1) # Prints False
print('Which one is biggest?', max(houses)) # Prints 'h3: 1101-square-foot Split'
print('Which is smallest?', min(houses)) # Prints 'h2: 846-square-foot Ranch'

如上所示,通过使用total_ordering,仅实现__eq__和__lt__,所有其他比较方法便自动实现。

如果编写了使类支持所有基本比较运算符的代码,那么total_ordering似乎并不是那么神奇:它从字面上定义了从每个比较支持方法到所有其他比较方法的映射。 因此,如果在解决方案中的类中定义了__lt __(),它将用于构建所有其他比较运算符。

class House:
    def __eq__(self, other):
        pass

    def __lt__(self, other):
        pass

# Methods created by @total_ordering
__le__ = lambda self, other: self < other or self == other
__gt__ = lambda self, other:  not (self < other or self == other)
__ge__ = lambda self, other: not (self < other)
__ne__ = lambda self, other: not self == other

以上是关于使类支持比较操作的主要内容,如果未能解决你的问题,请参考以下文章

比较有用的php代码片段

如何使类的功能默认

Sublime text3最全快捷键清单

支持动态或静态片段的不同屏幕尺寸?

如何在Python中使类成员进程安全

如何在 .net 中使类可序列化而无需 Serializable 属性