7

如何检查对象在 Python 中是否可排序/可排序?

我正在尝试为__init__我的二叉树类的方法实现基本类型检查,并且我希望能够检查节点的值是否可排序,如果不是则抛出错误。它类似于在哈希表的实现中检查哈希性。

我正在尝试完成类似于 Haskell 的(Ord a) => etc.预选赛的事情。Python中有类似的检查吗?

4

3 回答 3

6

如果你想知道一个对象是否可排序,你必须检查它是否实现了必要的比较方法。

Python 2.X中有两种不同的方式来实现这些方法:

  1. cmp 方法(每个示例相当于 Java 中的 compareTo)

    __cmp__(self, other): 返回 >0、0 或 <0 自我是否大于、等于或小于其他

  2. 丰富的比较方法

    __lt__, __gt__, __eq__, __le__, __ge__, __ne__

    sort() 函数调用该方法在实例之间进行必要的比较(实际上 sort 只需要__lt__or__gt__ 方法,但建议全部实现)

Python 3.X__cmp__,删除了有利于丰富的比较方法,因为有不止一种方法来做同样的事情确实违反了 Python 的“法律”。

因此,您基本上需要一个函数来检查这些方法是否由类实现:

# Python 2.X
def is_sortable(obj):
    return hasattr(obj, "__cmp__") or \
           hasattr(obj, "__lt__") or \
           hasattr(obj, "__gt__")

# Python 3.X
def is_sortable(obj):
    cls = obj.__class__
    return cls.__lt__ != object.__lt__ or \
           cls.__gt__ != object.__gt__

Python 2 和 3 需要不同的函数,因为 Python 3 中的未绑定方法、方法包装器和其他内部事物也发生了许多其他变化。

阅读此链接,您想更好地了解 Python 中的可排序对象:

PS:这是对我的第一个答案的完整重新编辑,但是因为我更好地调查了这个问题并且对此有了更清晰的想法,所以需要它:)

于 2013-10-28T14:17:52.497 回答
1

遗憾的是,仅检查您的对象是否实现lt是不够的。numpy 使用 '<' 运算符返回一个布尔数组,它没有真值。SQL Alchemy 使用它返回一个查询过滤器,它又没有真值。普通集合使用它来检查子集关系,因此

set1 = {1,2}
set2 = {2,3}
set1 == set2
False
set1 < set2
False
set1 > set2
False

我能想到的最好的部分解决方案(从未知类型的单个对象开始)是这样的,但是通过丰富的比较,似乎正式不可能确定可订购性:

 if hasattr(x, '__lt__'):
     try:
         isOrderable = ( ((x == x) is True) and ((x > x) is False)
                         and not isinstance(x, (set, frozenset)) )
     except:
         isOrderable = False
 else:
     isOrderable = False
于 2016-03-03T20:32:44.747 回答
0

已编辑

据我所知,所有列表都是可排序的,所以如果您想知道列表是否“可排序”,答案是肯定的,不知道它有什么元素。

class C:
    def __init__(self):
        self.a = 5
        self.b = "asd"

c = C()    
d = True

list1 = ["abc", "aad", c, 1, "b", 2, d]
list1.sort()
print list1
>>> [<__main__.C instance at 0x0000000002B7DF08>, 1, True, 2, 'aad', 'abc', 'b']

您可以确定您认为“可排序”的类型并实现一种方法来验证列表中的所有元素是否都是“可排序的”,如下所示:

def isSortable(list1):
    types = [int, float, str]
    res = True
    for e in list1:
        res = res and (type(e) in types)
    return res

print isSortable([1,2,3.0, "asd", [1,2,3]])
于 2013-10-27T03:22:55.403 回答