python元组比较,’不到’再访(2.7)

python tuple comparison, 'less than' revisited (2.7)

我想了解Python对于元组比较运算符的行为,特别是<(小于运算符)。

编辑:现在我明白了,谢谢你,雅罗斯劳给我一个明确的答案。

我的错误是认为1)"词典比较"是"字符串比较"的同义词,2)认为"字符串比较逻辑"应用于被比较的元组的每个元素,而不是在元组级别。它产生了==的有效行为,但对于<的有效行为不多。

很可能其他人会被这一殊荣所束缚。

excerpt from wikipedia (emphasis added)4: ...lexicographical order ... is a generalization
of the way the alphabetical order of words is based on the alphabetical order of their component letters.
This generalization consists primarily in defining a total order over the sequences ... of
elements of a finite totally ordered set, often called alphabet.

以下是原始问题文本…

等等,你说,这不是以前问过吗?对。。。很好地回答了==(平等)。我想了解为什么(1,2)<(1,3)会产生true(注意

我读过其他一些关于元组比较如何涉及到"每个元组中各个元素的词典比较"的问题。

问题:python-tuple比较奇怪的行为:这个问题是关于使用in操作符,我对<(小于),没有那么多in的行为感兴趣(至少还没有)。

问题:python-tuple比较:对于这一个,答案是(强调增加):

excerpt from Answer: Tuples are compared position by position: the first item of first
tuple is compared to the first item of the second tuple; if they are
not equal, this is the result of the comparison, else the second item
is considered, then the third and so on.

我理解这一点。编辑:*以为我明白了

为了推广到所有比较运算符,我将把答案修改为如下所示:

... the first item of first tuple is compared to the
first item of the second tuple; if the comaprison yields False
then the result of the tuple comaprison is also False. Otherwise
the comparison continues with the remaining items....
edit: this was wrong. Subtly wrong though, worked for == but not other relational operators.

我很难看出这对于<(小于)比较是如何工作的。他们链接到的python文档(修改为指向2.7)也在平等性方面讨论了这一点,强调补充说:

excerpt from python docs: Sequence types also support comparisons. In particular, tuples and
lists are compared lexicographically by comparing corresponding
elements. This means that to compare equal, every element must compare
equal and the two sequences must be of the same type and have the same
length. (For full details see Comparisons in the language reference.)
edit: at this point when writing up my original question I had tunnel vision on 'equality'.

我发现在比较语言引用中没有什么有用的地方;它没有涉及为什么(1,2)<(1,3)在比较运算符看起来应该为第一对元素生成false时生成true。

下面是一个玩具测试程序的输出示例;它的大部分工作正如我所期望的那样。请注意这两个嵌入的问题。

输出自"tcomp.py"(以下来源)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ python tcomp.py
tcomp.py
version= 2.7.12

---  empty tuples, intuitive, no surprises  ---
()  ==  ()  :  True
()   <  ()  :  False
()   >  ()  :  False

---  single-item tuples, equal values: intuitive, no surprises  ---
(1,)  ==  (1,)  :  True
(1,)   <  (1,)  :  False
(1,)   >  (1,)  :  False

---  single-item diff: intuitive, no surprises  ---
(1,)  ==  (2,)  :  False
(1,)   <  (2,)  :  True
(1,)   >  (2,)  :  False

---  double-item same: intuitive, no surprises  ---
(1, 2)  ==  (1, 2)  :  True
(1, 2)   <  (1, 2)  :  False
(1, 2)   >  (1, 2)  :  False
* Question: do a<b and a>b both yield False
* because Python short circuits on
* a[0] < b[0]    (and correspondingly a[0] > b[0] )?
* e.g. Python never bothers comparing second
* elements: a[1] < b[1]  (and, correspondinlgy, a[1] > b[1] ).

---  double-item 1st=same 2nd=diff: ??? What is with a<b ???
(1, 2)  ==  (1, 3)  :  False
(1, 2)   <  (1, 3)  :  True
(1, 2)   >  (1, 3)  :  False
* Question: Here I get the == comparison, that yields False like I would expect.
* But WHAT is going on with the < comparison?
* Even comapring"lexicographically", how does a[0] < b[0]
* actually yield True ?
* Is Python really  comparing a[0] < b[0] ?
* Because in my mental model that is the same as comparing: 1 < 1
* I kind of think 1 < 1 is supposed to be False, even if Python
* is comparing"1" <"1"  (e.g. lexicographically).
$

要添加到上面最后一个"*问题"中,按字典法对a[0]

tcomp.py版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import platform

def tupleInfo( a, b, msg ):
   # using labels instead of eval-style stuff to keep things simpler.
   print
   print '--- ' , msg , ' ---'
   print a, ' == ', b, ' : ', a == b
   print a, '  < ', b, ' : ', a  < b
   print a, '  > ', b, ' : ', a  > b

print 'tcomp.py'
print 'version=', platform.python_version()

# let's start with some empty tuples.
e1 = tuple()
e2 = tuple()
tupleInfo( tuple( )         , tuple( )         , 'empty tuples,intuitive, no surprises' )
tupleInfo( tuple( [ 1 ] )   , tuple( [ 1 ] )   , 'single-item tuples, equal values: intuitive, no surprises' )
tupleInfo( tuple( [ 1 ] )   , tuple( [ 2 ] )   , 'single-item diff: intuitive, no surprises' )
tupleInfo( tuple( [ 1, 2 ] ), tuple( [ 1, 2 ] ), 'double-item same: intuitive, no surprises' )

print '* Question: do a<b and a>b both yield False '
print '* because Python short circuits on'
print '* a[0] < b[0]    (and correspondingly a[0] > b[0] )?'
print '* e.g. Python never bothers comparing second'
print '* elements: a[1] < b[1]  (and, correspondinlgy, a[1] > b[1] ).'


tupleInfo( tuple( [ 1, 2 ] ), tuple( [ 1, 3 ] ), 'double-item 1st=same 2nd=diff: ??? What is with a<b ???' )

print '* Question: Here I get the == comparison, that yields False like I would expect.'
print '* But WHAT is going on with the < comparison?'
print '* Even comapring"lexicographically", how does a[0] < b[0]'
print '* actually yield True ?'
print '* Is Python really  comparing a[0] < b[0] ?'
print '* Because in my mental model that is the same as comparing: 1 < 1'
print '* I kind of think 1 < 1 is supposed to be False, even if Python'
print '* is comparing"1" <"1"  (e.g. lexicographically).'


答案在于"词汇学"。这意味着,python会比较从第一个位置开始的元组。在词汇表或词汇表中使用这个顺序——如果a出现在b之前,单词a比单词b小,那么我们可以比较两个单词,如'anthrax''antipodes',其中三个第一个字母相等:'anthrax'出现在'antipodes'之前的词汇表中,因此,声明'anthrax' < 'antipodes'True

这种比较可以这样表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def isSmaller(a, b): # returns true if a<b, false if a>=b
    for i in xrange(0, a.__len__()): # for every elementof a, starting from left
        if b.__len__() <= i: # if a starts with b, but a is longer, eg. b='ab', a='ab...'
            return False
        if a[i] < b[i]: # if a starts like b, but there is difference on i-th position,
                        # eg. a='abb...', b='abc...',
            return True
        if a[i] > b[i]: # eg. a='abc...', b='abb...',
            return False
        if a[i] == b[i]: # if there is no difference, check the next position
            pass
    if a.__len__() < b.__len__(): # if b starts with a, but b is longer, eg. a='ac', b='ac...'
        return True
    else: # else, ie. when a is the same as b, eg. a='acdc', b='acdc'
        return False


print (1,2,3)<(1,2)
print (1,2,3)<(1,2,3)
print (1,2,3)<(1,3,2)
print isSmaller((1,2,3),(1,2))
print isSmaller((1,2,3),(1,2,3))
print isSmaller((1,2,3),(1,3,2))

输出:

1
2
3
4
5
6
False
False
True
False
False
True