TypeError:不可排序类型:Python 3中的tuple()

时间:2021-10-05 17:03:20

The below code is ordering poker hands. It works well in Python 2.7 but it does not work in Python 3. What are the changes that have been made causing it to give an TypeError: unorderable types: tuple() < int()?

下面的代码是命令扑克手。它在Python 2.7中工作得很好,但在Python 3中不工作。已经做了哪些更改,导致它给出一个TypeError:无序类型:tuple() < int()?

def poker(hands):
    scores = [(i, score(hand.split())) for i, hand in enumerate(hands)]
    winner = sorted(scores , key=lambda x:x[1])[-1][0]
    return hands[winner]

def score(hand):
    ranks = '23456789TJQKA'
    rcounts = {ranks.find(r): ''.join(hand).count(r) for r, _ in hand}.items()
    score, ranks = zip(*sorted((cnt, rank) for rank, cnt in rcounts)[::-1])
    if len(score) == 5:
        if ranks[0:2] == (12, 3): #adjust if 5 high straight
            ranks = (3, 2, 1, 0, -1)
        straight = ranks[0] - ranks[4] == 4
        flush = len({suit for _, suit in hand}) == 1
        '''no pair, straight, flush, or straight flush'''
        score = ([1, (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]
    return score, ranks

 >>> poker(['8C TS KC 9H 4S', '7D 2S 5D 3S AC', '8C AD 8D AC 9C', '7C 5H 8D TD KS'])
 '8C AD 8D AC 9C'

2 个解决方案

#1


4  

It is happening because you are comparing int and a tuple. In python2x, default cmp operation was defined for different inbuilt objects, which has been removed in python3.

这是因为您正在比较int和tuple。在python2x中,为不同的内置对象定义了默认的cmp操作,在python3中已经删除了。

Python 3 ignores the cmp() method. In addition to this, the cmp() function is gone! This typically results in your converted code raising a TypeError: unorderable types error. So you need to replace the cmp() method with rich comparison methods instead. To support sorting you only need to implement lt(), the method used for the “less then” operator, <.

Python 3忽略了cmp()方法。除此之外,cmp()函数消失了!这通常会导致转换后的代码产生一个类型错误:无序类型错误。因此,您需要用丰富的比较方法替代cmp()方法。要支持排序,只需实现lt(),这是用于“less then”操作符 <的方法。< p>

Official documentation

官方文档

So, in python2, we can do something like this

在python2里,我们可以这样做

(2, 3) > 2

but it raises TypeError in python3. If this code was working in python2, then most probably it was bug that was implicitly being handled by default comparison behaviour.

但是在python3里它提出了类型错误。如果这段代码在python2中工作,那么很可能是bug被默认的比较行为隐式地处理了。

Now in your example:-

现在在你的例子:-

#value of scores that are being compared for sorting
scores = [(0, (1, (11, 8, 7, 6, 2))), (1, (1, (12, 5, 3, 1, 0))), (2, ((2, 2, 1), (12, 6, 7))), (3, (1, (11, 8, 6, 5, 3)))]

print(type(scores[1][1][0])) # <class 'int'>
print(type(scores[2][1][0])) # <class 'tuple'>

which as I have explained does not work in python3. What is the criteria you are assuming for comparing a tuple and an int.

正如我所解释的,这在python3里是行不通的。您在比较一个元组和一个整数时的标准是什么。

If you really want to compare different type of objects, then you need to roll out your own version of tuple, and use that object in your scores instead.

如果您真的想比较不同类型的对象,那么您需要推出自己的tuple版本,并在您的分数中使用该对象。

class MyTuple(tuple):

     def __lt__(self, other):
        pass

Default tuple comparison python 2

默认的tuple比较python 2

Note:- I don't recommend using this approach. It was just for instructional purposes.

注意:-我不建议使用这种方法。这只是出于教学目的。

#2


2  

The solution: Convert the integer into a tuple: score = ([(1, ), (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]

解决方案:将整数转换为一个元组:score = ([(1,), (3,1,1,1)], [(3,1,1,2), (5,)]

#1


4  

It is happening because you are comparing int and a tuple. In python2x, default cmp operation was defined for different inbuilt objects, which has been removed in python3.

这是因为您正在比较int和tuple。在python2x中,为不同的内置对象定义了默认的cmp操作,在python3中已经删除了。

Python 3 ignores the cmp() method. In addition to this, the cmp() function is gone! This typically results in your converted code raising a TypeError: unorderable types error. So you need to replace the cmp() method with rich comparison methods instead. To support sorting you only need to implement lt(), the method used for the “less then” operator, <.

Python 3忽略了cmp()方法。除此之外,cmp()函数消失了!这通常会导致转换后的代码产生一个类型错误:无序类型错误。因此,您需要用丰富的比较方法替代cmp()方法。要支持排序,只需实现lt(),这是用于“less then”操作符 <的方法。< p>

Official documentation

官方文档

So, in python2, we can do something like this

在python2里,我们可以这样做

(2, 3) > 2

but it raises TypeError in python3. If this code was working in python2, then most probably it was bug that was implicitly being handled by default comparison behaviour.

但是在python3里它提出了类型错误。如果这段代码在python2中工作,那么很可能是bug被默认的比较行为隐式地处理了。

Now in your example:-

现在在你的例子:-

#value of scores that are being compared for sorting
scores = [(0, (1, (11, 8, 7, 6, 2))), (1, (1, (12, 5, 3, 1, 0))), (2, ((2, 2, 1), (12, 6, 7))), (3, (1, (11, 8, 6, 5, 3)))]

print(type(scores[1][1][0])) # <class 'int'>
print(type(scores[2][1][0])) # <class 'tuple'>

which as I have explained does not work in python3. What is the criteria you are assuming for comparing a tuple and an int.

正如我所解释的,这在python3里是行不通的。您在比较一个元组和一个整数时的标准是什么。

If you really want to compare different type of objects, then you need to roll out your own version of tuple, and use that object in your scores instead.

如果您真的想比较不同类型的对象,那么您需要推出自己的tuple版本,并在您的分数中使用该对象。

class MyTuple(tuple):

     def __lt__(self, other):
        pass

Default tuple comparison python 2

默认的tuple比较python 2

Note:- I don't recommend using this approach. It was just for instructional purposes.

注意:-我不建议使用这种方法。这只是出于教学目的。

#2


2  

The solution: Convert the integer into a tuple: score = ([(1, ), (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]

解决方案:将整数转换为一个元组:score = ([(1,), (3,1,1,1)], [(3,1,1,2), (5,)]