我们都知道, python是一个强类型的语言, 也是一个动态类型的语言. 但是在python2.X系列中, 这个强类型是需要打折扣的, 是非常接近强类型.

我们来看下面的代码片段

In [1]: 'a' < 1000
Out[1]: False

字符串和整型居然可以比较, 这个是个非常奇怪的行为. 强类型的语言是不应该允许有这种类型间的隐式转换的, 所以这种比较应该是报错的才对. Java就是这样的一个语言. 不过强类型的语言中, 是可以各种数字类型之间存在隐式转换的.

python的这个字符串和整形的比较是非常特别的, python中是没有字符类型(char)的, 单引号和双引号都是字符串类型.

这字符串和整型的比较是按照ASCII表的顺序么? 显然也不是. 'a'对应的ascii码是97, 'a' < 1000就是97 < 1000,  应该返回True才对.

官网文档(参考3)对这个东西作出这样的解释:

CPython implementation detail: Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.

CPython的实现细节汇总:

规则1: 除数字类型外不同类型的对象是按照类型的名字来排序的.

规则2: 不支持比较操作的相同类型的对象是按照地址来排序的.

[我查到stackoverflow(参考2)也有人对这个东西作出补充.]

规则3: 比较两个字符串或两个数字类型, 比较结果是符合预期的(字符串是字典顺序, 整型是数字大小的顺序)

原文: When you order two strings or two numeric types the ordering is done in the expected way (lexicographic ordering for string, numeric ordering for integers).

规则4:比较数字类型和非数字类型的时候, 数字类型在前(就是数字类型 < 非数字类型)

原文: When you order a numeric and a non-numeric type, the numeric type comes first.

规则1的例外: 旧风格的类小于新风格的类.

原文: One exception is old-style classes that always come before new-style classes.

我们可以发现, 其实CPython的强类型不是真的, 存在很多陷进.

下面我对这几个查到的规则进行验证

class Foo(object):
pass class Bar(object):
pass # 规则1
print Foo() > Bar() # 规则2
a, b = Foo(), Foo()
print id(a) > id(b), id(a), id(b)
print a > b # 规则3
print 100 > 1
print 'b' > 'a' class Foo:
pass class Bar(object):
pass # 规则4
print Foo > 1000 # classobj > int
f = Foo()
print id(f) < id(1000), id(f), id(1000), id(1000)
print f < 1000 # old-style class instance > int 应该是 Foo() > 1000, 这不符合规则4, Foo是old-style类
print Bar() > 1000 # new-style class instance > int print 'a' > 1000 # str > int
print {} > 1000 # dict > int
print [] > 1000 # list > int
print (1,) > 1000 # tuple > int # 规则1的例外
print Foo() < Bar() # old-style class < new-style class

上面代码的所有比较表达式都是True. 测试环境是2.7.6

我发现这些规则也出现了例外, Foo() > 1000, Foo是old-style类, 是这个原因么? 不理解, 反正这是个非常困惑的实现方式.

如果有知道的朋友, 麻烦留言告知一下, 这个实现真的是非常困惑. 我们日常使用的过程中, 要非常注意判断类型之后再比较, 防止这类陷进.

幸运的是python 3.X已经修正了这个问题, 参考2的例子

>>> '10' > 5
Traceback (most recent call last):
File "", line 1, in
'10' > 5
TypeError: unorderable types: str() > int()

CPython获取对象地址的方法是id(), 官网给出了这样的解释: This is the address of the object in memory.

水平有限, 欢迎拍砖!

参考资料:

  1. 麻省理工学院公开课:计算机科学及编程导论 第二课 分支, 条件和循环 (可以在网易公开课中找到)
  2. http://stackoverflow.com/questions/3270680/how-does-python-compare-string-and-int
  3. http://docs.python.org/2/library/stdtypes.html#comparisons
  4. http://docs.python.org/2/library/functions.html#id

Python tricks(5) -- string和integer的comparison操作的更多相关文章

  1. 【leetcode❤python】 8. String to Integer (atoi)

    #-*- coding: UTF-8 -*-#需要考虑多种情况#以下几种是可以返回的数值#1.以0开头的字符串,如01201215#2.以正负号开头的字符串,如'+121215':'-1215489' ...

  2. 【leetcode】String to Integer (atoi)

    String to Integer (atoi) Implement atoi to convert a string to an integer. Hint: Carefully consider ...

  3. No.008 String to Integer (atoi)

    8. String to Integer (atoi) Total Accepted: 112863 Total Submissions: 825433 Difficulty: Easy Implem ...

  4. 【LeetCode】7 & 8 - Reverse Integer & String to Integer (atoi)

    7 - Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 Notic ...

  5. leetcode第八题 String to Integer (atoi) (java)

    String to Integer (atoi) time=272ms   accepted 需考虑各种可能出现的情况 public class Solution { public int atoi( ...

  6. leetcode day6 -- String to Integer (atoi) &amp;&amp; Best Time to Buy and Sell Stock I II III

    1.  String to Integer (atoi) Implement atoi to convert a string to an integer. Hint: Carefully con ...

  7. String to Integer (atoi) - 字符串转为整形,atoi 函数(Java )

    String to Integer (atoi) Implement atoi to convert a string to an integer. [函数说明]atoi() 函数会扫描 str 字符 ...

  8. Kotlin实现LeetCode算法题之String to Integer (atoi)

    题目String to Integer (atoi)(难度Medium) 大意是找出给定字串开头部分的整型数值,忽略开头的空格,注意符号,对超出Integer的数做取边界值处理. 方案1 class ...

  9. String与Integer问题

    今天分享一下关于最近面试的问题,临近春节,而我在茫茫人海中奔波,今天面试了来到了中关村科技园,挺气派的,之前也是在外面看看,今天就去了,心里有点激动,恰好,正好赶上了上班时,看见它们的努力,我感到再累 ...

随机推荐

  1. Spring加载xsd文件报错:because 1) could not find the document; 2) the document could not be read...

    Spring启动时加载xml文件的过程: spring在加载xsd文件时总是先试图在本地查找xsd文件(spring的jar包中已经包含了所有版本的xsd文件),如果没有找到,才会转向去URL指定的路 ...

  2. Linux wc

    命令参数: -c 统计字节数. -l 统计行数. -m 统计字符数.这个标志不能与 -c 标志一起使用. -w 统计字数.一个字被定义为由空白.跳格或换行字符分隔的字符串. -L 打印最长行的长度. ...

  3. JPA的锁机制

    JPA 各种实体锁模式的区别 字数2084 阅读304 评论0 喜欢4 为了能够同步访问实体,JPA提供了2种锁机制.这两种机制都可以避免两个事务中的其中一个,在不知情的情况下覆盖另一个事务的数据. ...

  4. CCCC L2-013. 红色警报 连通分量

    题解:将问题转化成连通分量.每次失去一座城市,切断其所有的边,算一次现在的连通分量.若增量大于1,则发出警报. 至于如何算连通分量,直接用tarjan模板 坑://我昨天晚上半夜敲的模板,把一个算所有 ...

  5. HTML5 Storage(永久存储)

    localStorage.aa="aa"; //存储了一个key为aa并且value为aa的键值对: localStorage.setItem("bb", &q ...

  6. 【xargs -i】复制文件夹中前100个文件

    复制前一万个文件到 tmp 下 |xargs -i cp {} /tmp 复制后一万个文件到 tmp 下 |xargs -i cp {} /tmp 查看linux下文件夹文件数目 ls -l |gre ...

  7. Dungeon Master---2251(bfs)

    http://poj.org/problem?id=2251 有一个三维的牢房地图 求从S点走E点的最小时间: #include<stdio.h> #include<string.h ...

  8. javaScript高级教程(二)Scope Chain & Closure Example

    <!DOCTYPE html> <html> <head> <meta charset=gb2312 /> <title>js</ti ...

  9. qt——常用的布局方法

    布局相关对象及简介 窗体上的所有的控件必须有一个合适的尺寸和位置.Qt提供了一些类负责排列窗体上的控件,主要有:QHBoxLayout,QVBoxLayout,QGridLayout,QStackLa ...

  10. MySQL找出锁等待

    1.服务器级别的锁等待 可以通过show processlist看到等待锁的线程id,但是无法知道究竟哪个线程持有锁 可以通过mysqladmin debug 相关等待锁的线程以及谁持有锁可以在错误日 ...