zoukankan      html  css  js  c++  java
  • Python tricks(5) -- string和integer的comparison操作

    我们都知道, 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
  • 相关阅读:
    C++——多态性
    C++——继承与派生
    C++——字符串处理
    C++——深拷贝
    C++——浅拷贝
    C++——动态内存分配3
    C++——动态内存分配2-创建对象数组
    C++——动态内存分配1
    C++——指针5
    C++——指针4
  • 原文地址:https://www.cnblogs.com/icejoywoo/p/3546704.html
Copyright © 2011-2022 走看看