zoukankan      html  css  js  c++  java
  • python2.7和 python3.4但是不要

    很多 Python 刚開始学习的人想知道他们应该从 Python 的哪个版本号開始学习。对于这个问题我的答案是 “你学习你喜欢的教程的版本号。然后检查他们之间的不同。

    "

    可是假设你開始一个新项目,而且有选择权?我想说的是眼下没有对错,仅仅要你计划使用的库 Python 2.7.x 和 Python 3.x 两方都支持的话。

    虽然如此。当在编写它们中的不论什么一个的代码,或者是你计划移植你的项目的时候。是很值得看看这两个主要流行的 Python 版本号之间的区别的,以便避免常见的陷阱。

    章节

    future模块

    Python 3.x 介绍的 一些Python 2 不兼容的keyword和特性能够通过在 Python 2 的内置__future__模块导入。假设你计划让你的代码支持 Python 3.x。建议你使用__future__模块导入。比如。假设我想要 在Python 2 中表现 Python 3.x 中的整除,我们能够通过例如以下导入

    from __future__ import division
    

    很多其它的__future__模块可被导入的特性被列在下表中:

    feature optional in mandatory in effect
    nested_scopes 2.1.0b1 2.2 PEP 255: Simple Generators
    division 2.2.0a2 3.0 PEP 328: Imports: Multi-Line and Absolute/Relative
    with_statement 2.5.0a1 2.6 PEP 3105: Make print a function
    unicode_literals 2.6.0a2 3.0 <a rel="nofollow" href="http://legacy.python.org/dev/peps/pep-3112/" """="" target="_blank" style="color: rgb(128, 0, 128); text-decoration: none; outline-style: none;">PEP 3112: Bytes literals in Python 3000

    (Source:https://docs.python.org/2/library/future.html)

    from platform import python_version
    

    print函数

    [跳转到章节预览]

    非常琐碎。而print语法的变化可能是最广为人知的了。可是仍值得一提的是: Python 2 的print声明已经被print()函数代替了,这意味着我们必须包装我们想打印在小括号里的对象。


    Python 2 不具有额外的小括号问题。但对照一下。假设我们依照 Python 2 的方式不使用小括号调用print函数。Python 3 将抛出一个语法异常(SyntaxError)。

    Python 2

    print 'Python', python_version()
    print 'Hello, World!'
    print('Hello, World!') print "text", ; print 'print more text on the same line' 
    Python 2.7.6
    Hello, World!
    Hello, World!
    text print more text on the same line
    
    

    Python 3

    print('Python', python_version()) print('Hello, World!')  print("some text,", end="")  print(' print more text on the same line') 
    Python 3.4.1
    Hello, World!
    some text, print more text on the same line
    
    print 'Hello, World!'
    
    File "<ipython-input-3-139a7c5835bd>", line 1
        print 'Hello, World!'
                            ^
    SyntaxError: invalid syntax
    

    注意

    以上通过 Python 2 使用Printing "Hello, World"是很正常的。虽然如此。假设你有多个对象在小括号里,我们将创建一个元组,由于print在 Python 2 中是一个声明,而不是一个函数调用。

    print 'Python', python_version()
    print('a', 'b') print 'a', 'b' 
    Python 2.7.7
    ('a', 'b')
    a b
    

    整除

    [跳转到章节预览]

    假设你正在移植代码。这个变化是特别危急的。

    或者你在 Python 2 上运行 Python 3 的代码。由于这个整除的变化表如今它会被忽视(即它不会抛出语法异常)。

    因此,我还是倾向于使用一个float(3)/23/2.0取代在我的 Python 3 脚本保存在 Python 2 中的3/2的一些麻烦(而且反而过来也一样。我建议在你的 Python 2 脚本中使用from __future__ import division

    Python 2

    print 'Python', python_version()
    print '3 / 2 =', 3 / 2
    print '3 // 2 =', 3 // 2
    print '3 / 2.0 =', 3 / 2.0
    print '3 // 2.0 =', 3 // 2.0
    
    Python 2.7.6
    3 / 2 = 1
    3 // 2 = 1
    3 / 2.0 = 1.5
    3 // 2.0 = 1.0
    

    Python 3

    print('Python', python_version()) print('3 / 2 =', 3 / 2) print('3 // 2 =', 3 // 2) print('3 / 2.0 =', 3 / 2.0) print('3 // 2.0 =', 3 // 2.0) 
    Python 3.4.1
    3 / 2 = 1.5
    3 // 2 = 1
    3 / 2.0 = 1.5
    3 // 2.0 = 1.0
    

    Unicode

    [跳转到章节预览]

    Python 2 有ASCII str()类型,unicode()是单独的。不是 byte 类型。

    如今, 在 Python 3,我们终于有了Unicode (utf-8)字符串,以及一个字节类:bytebytearrays

    Python 2

    print 'Python', python_version()
    
    Python 2.7.6
    
    print type(unicode('this is like a python3 str type'))
    
    <type 'unicode'>
    
    print type(b'byte type does not exist')
    
    <type 'str'>
    
    print 'they are really' + b' the same'
    
    they are really the same
    
    print type(bytearray(b'bytearray oddly does exist though'))
    
    <type 'bytearray'>
    

    Python 3

    print('Python', python_version()) print('strings are now utf-8 u03BCnicou0394é!')  Python 3.4.1 strings are now utf-8 μnicoΔé! 
    print('Python', python_version(), end="")
    print(' has', type(b' bytes for storing data'))
    
    Python 3.4.1 has <class 'bytes'> 
    print('and Python', python_version(), end="") print(' also has', type(bytearray(b'bytearrays')))  and Python 3.4.1 also has <class 'bytearray'> 
    'note that we cannot add a string' + b'bytes for data'
    
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-13-d3e8942ccf81> in <module>() ----> 1 'note that we cannot add a string' + b'bytes for data'  TypeError: Can't convert 'bytes' object to str implicitly 

    xrange

    [跳转到章节预览]

    在 Python 2 中xrange()创建迭代对象的使用方法是很流行的。

    比方: for 循环或者是列表/集合/字典推导式。

    这个表现十分像生成器(比方。“惰性求值”)。

    可是这个xrange-iterable是无穷的。意味着你能够无限遍历。

    因为它的惰性求值,假设你不得只不遍历它一次,xrange()函数 比range()更快(比方 for 循环)。虽然如此,对照迭代一次。不建议你反复迭代多次,由于生成器每次都从头開始。

    在 Python 3 中,range()是像xrange()那样实现以至于一个专门的xrange()函数都不再存在(在 Python 3 中xrange()会抛出命名异常)。

    import timeit
    
    n = 10000
    def test_range(n):
        return for i in range(n):
            pass
    
    def test_xrange(n):
        for i in xrange(n):
            pass   
    

    Python 2

    print 'Python', python_version()
    
    print 'ntiming range()' 
    %timeit test_range(n)
    
    print 'nntiming xrange()' 
    %timeit test_xrange(n)
    
    Python 2.7.6
    
    timing range()
    1000 loops, best of 3: 433 µs per loop
    
    
    timing xrange()
    1000 loops, best of 3: 350 µs per loop
    

    Python 3

    print('Python', python_version())
    
    print('ntiming range()')
    %timeit test_range(n)
    
    Python 3.4.1
    
    timing range()
    1000 loops, best of 3: 520 µs per loop
    
    print(xrange(10)) --------------------------------------------------------------------------- NameError                                 Traceback (most recent call last) <ipython-input-5-5d8f9b79ea70> in <module>() ----> 1 print(xrange(10))
    
    NameError: name 'xrange' is not defined
    

    Python 3 中的range对象的__contains__方法

    另外一件值得一提的事情就是在 Python 3 中range有一个新的__contains__方法(感谢Yuchen Ying指出了这个),__contains__方法能够加速"查找"在 Python 3.x 中显著的整数和布尔类型。

    x = 10000000
    
    def val_in_range(x, val):
        return val in range(x)
    
    def val_in_xrange(x, val):
        return val in xrange(x)
    
    print('Python', python_version())
    assert(val_in_range(x, x/2) == True)
    assert(val_in_range(x, x//2) == True)
    %timeit val_in_range(x, x/2)
    %timeit val_in_range(x, x//2)
    
    Python 3.4.1
    1 loops, best of 3: 742 ms per loop
    1000000 loops, best of 3: 1.19 µs per loop
    

    基于以上的timeit的结果。当它使一个整数类型,而不是浮点类型的时候,你能够看到运行查找的速度是 60000 倍快。虽然如此。由于 Python 2.x 的range或者是xrange没有一个__contains__方法,这个整数类型或者是浮点类型的查询速度不会相差太大。

    print 'Python', python_version()
    assert(val_in_xrange(x, x/2.0) == True)
    assert(val_in_xrange(x, x/2) == True)
    assert(val_in_range(x, x/2) == True)
    assert(val_in_range(x, x//2) == True)
    %timeit val_in_xrange(x, x/2.0)
    %timeit val_in_xrange(x, x/2)
    %timeit val_in_range(x, x/2.0)
    %timeit val_in_range(x, x/2)
    
    Python 2.7.7
    1 loops, best of 3: 285 ms per loop
    1 loops, best of 3: 179 ms per loop
    1 loops, best of 3: 658 ms per loop
    1 loops, best of 3: 556 ms per loop
    

    以下说下__contain__方法并没有增加到 Python 2.x 中的证据:

    print('Python', python_version()) range.__contains__  Python 3.4.1  <slot wrapper '__contains__' of 'range' objects> 
    print 'Python', python_version()
    range.__contains__
    
    
    Python 2.7.7
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-7-05327350dafb> in <module>()       1 print 'Python', python_version() ----> 2 range.__contains__  AttributeError: 'builtin_function_or_method' object has no attribute '__contains__' 
    print 'Python', python_version()
    xrange.__contains__
    
    Python 2.7.7
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-8-7d1a71bfee8e> in <module>()       1 print 'Python', python_version() ----> 2 xrange.__contains__  AttributeError: type object 'xrange' has no attribute '__contains__' 

    **注意在 Python 2 和 Python 3 中速度的不同***

    有些猿类指出了 Python 3 的range()和 Python 2 的xrange()之间的速度不同。由于他们是用同样的方法实现的。因此期望同样的速度。

    虽然如此。这事实在于 Python 3 倾向于比 Python 2 执行的慢一点。

    def test_while():
        i = 0
        while i < 20000:
            i += 1
        return
    
    print('Python', python_version())
    %timeit test_while()
    
    Python 3.4.1
    100 loops, best of 3: 2.68 ms per loop
    
    print 'Python', python_version()
    %timeit test_while()
    
    Python 2.7.6
    1000 loops, best of 3: 1.72 ms per loop
    

    Raising exceptions

    [跳转到章节预览]

    Python 2 接受新旧两种语法标记,在 Python 3 中假设我不用小括号把异常參数括起来就会堵塞(而且反过来引发一个语法异常)。

    Python 2

    print 'Python', python_version()
    
    Python 2.7.6
    
    raise IOError, "file error"
    
    
    ---------------------------------------------------------------------------
    IOError                                   Traceback (most recent call last) <ipython-input-8-25f049caebb0> in <module>() ----> 1 raise IOError, "file error"  IOError: file error 
    raise IOError("file error")
    
    ---------------------------------------------------------------------------
    IOError                                   Traceback (most recent call last)
    <ipython-input-9-6f1c43f525b2> in <module>() ----> 1 raise IOError("file error")  IOError: file error 

    Python 3

    print('Python', python_version())  Python 3.4.1 
    raise IOError, "file error"
    
      File "<ipython-input-10-25f049caebb0>", line 1
        raise IOError, "file error"
                     ^
    SyntaxError: invalid syntax
    The proper way to raise an exception in Python 3:
    
    print('Python', python_version()) raise IOError("file error")   Python 3.4.1 --------------------------------------------------------------------------- OSError                                   Traceback (most recent call last) <ipython-input-11-c350544d15da> in <module>()       1 print('Python', python_version()) ----> 2 raise IOError("file error")
    
    OSError: file error
    

    Handling exceptions

    在 Python 3 中处理异常也轻微的改变了,在 Python 3 中我们如今使用as作为关键词。

    python 2

    print 'Python', python_version()
    try:
        let_us_cause_a_NameError
    except NameError, err:
        print err, '--> our error message'
    
    
    Python 2.7.6
    name 'let_us_cause_a_NameError' is not defined --> our error message
    

    Python 3

    print('Python', python_version())
    try:
        let_us_cause_a_NameError
    except NameError as err:
        print(err, '--> our error message')
    
    
    Python 3.4.1
    name 'let_us_cause_a_NameError' is not defined --> our error message
    

    next() 函数 and .next() 方法

    由于next() (.next())是一个如此普通的使用函数(方法)。这里有另外一个语法改变(或者是实现上改变了),值得一提的是:在 Python 2.7.5 中函数和方法你都能够使用,next()函数在 Python 3 中一直保留着(调用.next()抛出属性异常)。

    Python 2

    print 'Python', python_version()
    
    my_generator = (letter for letter in 'abcdefg')
    
    next(my_generator) my_generator.next() 
    Python 2.7.6
    
    'b'
    

    Python 3

    print('Python', python_version())  my_generator = (letter for letter in 'abcdefg')  next(my_generator) 
    Python 3.4.1
    
    'a'
    
    my_generator.next()
    
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last) <ipython-input-14-125f388bb61b> in <module>() ----> 1 my_generator.next()  AttributeError: 'generator' object has no attribute 'next' 

    For 循环变量和全局命名空间泄漏

    好消息:在 Python 3.x 中 for 循环变量不会再导致命名空间泄漏。

    在 Python 3.x 中做了一个改变,在What’s New In Python 3.0中有例如以下描写叙述:

    "列表推导不再支持 [... for var in item1, item2, ...] 这种语法。使用 [... for var in (item1, item2, ...)] 取代。也须要提醒的是列表推导有不同的语义:  他们关闭了在 `list()` 构造器中的生成器表达式的语法糖, 而且特别是循环控制变量不再泄漏进周围的作用范围域."
    

    Python 2

    print 'Python', python_version()
    
    i = 1
    print 'before: i =', i
    
    print 'comprehension: ', [i for i in range(5)]
    
    print 'after: i =', i
    
    
    Python 2.7.6
    before: i = 1
    comprehension:  [0, 1, 2, 3, 4]
    after: i = 4
    

    Python 3

    print('Python', python_version())
    
    i = 1
    print('before: i =', i)
    
    print('comprehension:', [i for i in range(5)])
    
    print('after: i =', i)
    
    
    Python 3.4.1
    before: i = 1
    comprehension: [0, 1, 2, 3, 4]
    after: i = 1
    

    比較不可排序类型

    在 Python 3 中的另外一个变化就是当对不可排序类型做比較的时候。会抛出一个类型错误。

    Python 2

    print 'Python', python_version()
    print "[1, 2] > 'foo' = ", [1, 2] > 'foo'
    print "(1, 2) > 'foo' = ", (1, 2) > 'foo'
    print "[1, 2] > (1, 2) = ", [1, 2] > (1, 2)
    
    
    Python 2.7.6
    [1, 2] > 'foo' =  False
    (1, 2) > 'foo' =  True
    [1, 2] > (1, 2) =  False
    

    Python 3

    print('Python', python_version()) print("[1, 2] > 'foo' = ", [1, 2] > 'foo') print("(1, 2) > 'foo' = ", (1, 2) > 'foo') print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2))   Python 3.4.1 --------------------------------------------------------------------------- TypeError                                 Traceback (most recent call last) <ipython-input-16-a9031729f4a0> in <module>()       1 print('Python', python_version()) ----> 2 print("[1, 2] > 'foo' = ", [1, 2] > 'foo')
          3 print("(1, 2) > 'foo' = ", (1, 2) > 'foo')
          4 print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2))
    
    TypeError: unorderable types: list() > str()
    

    通过input()解析用户的输入

    幸运的是。在 Python 3 中已经攻克了把用户的输入存储为一个str对象的问题。

    为了避免在 Python 2 中的读取非字符串类型的危急行为,我们不得不使用raw_input()取代。

    Python 2

    Python 2.7.6 
    [GCC 4.0.1 (Apple Inc. build 5493)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    
    >>> my_input = input('enter a number: ')
    
    enter a number: 123
    
    >>> type(my_input)
    <type 'int'>
    
    >>> my_input = raw_input('enter a number: ')
    
    enter a number: 123
    
    >>> type(my_input)
    <type 'str'>
    

    Python 3

    Python 3.4.1 
    [GCC 4.2.1 (Apple Inc. build 5577)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    
    >>> my_input = input('enter a number: ')
    
    
    enter a number: 123
    
    
    >>> type(my_input)
    <class 'str'>
    

    返回可迭代对象,而不是列表

    假设在 xrange 章节看到的,如今在 Python 3 中一些方法和函数返回迭代对象 -- 取代 Python 2 中的列表

    由于我们通常那些遍历仅仅有一次,我觉得这个改变对节约内存非常有意义。

    虽然如此,它也是可能的。相对于生成器 --- 如须要遍历多次。它是不那么高效的。

    而对于那些情况下,我们真正须要的是列表对象。我们能够通过list()函数简单的把迭代对象转换成一个列表。

    Python 2

    print 'Python', python_version() 
    
    print range(3) 
    print type(range(3))
    
    
    Python 2.7.6
    [0, 1, 2]
    <type 'list'>
    

    Python 3

    print('Python', python_version())  print(range(3)) print(type(range(3))) print(list(range(3)))   Python 3.4.1 range(0, 3) <class 'range'> [0, 1, 2] 

    在 Python 3 中一些常常使用到的不再返回列表的函数和方法

    • zip()

    • map()

    • filter()

    • dictionary's .keys() method

    • dictionary's .values() method

    • dictionary's .items() method

    很多其它的关于 Python 2 和 Python 3 的文章

    以下是我建议兴许的关于 Python 2 和 Python 3 的一些好文章。

    移植到 Python 3

    Python 3 的拥护者和反对者

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Ubuntu系统下《汇编语言》环境配置

    GetDiskFreeSpaceEx的使用
    夏走了
    小笨妞
    项目管理怎么可以这样子!


    浪费
    查找文件夹
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4718083.html
Copyright © 2011-2022 走看看