Python 2.x 与 3​​.x 版本区别

本章节,我们将介绍一下 Python 3.X 和 Python2.X 之间的差别

首先,第一句话

新开发的项目,首先推荐你使用 Python3

Python 3​​.X 版本,简称 Py3k, 对于 Python 的早期版本,这是一个重大的不兼容的升级

为了不带入过多的累赘,Python 3.X 在设计的时候没有考虑向下相容

许多针对早期 Python 版本设计的程序和库都无法在 Python 3.0 上正常执行

为了照顾现有程序,Python 2.6-2.7 作为一个过渡版本,基本使用了 Python 2.x 的语法和库,同时考虑了向 Python 3.0 的迁移,允许使用部分 Python 3.X 的语法与函数

Python 3.X 的变化主要在以下几个方面

1. print()

Py3.X print 语句没有了,取而代之的是 print() 函数

Py2.X print 语句

>>> print "Hello", ' ', 'World'
Hello   World

Py3.X print() 函数

>>> print 'Hello', ' ', 'World'
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('Hello', ' ', 'World')?
>>> print('Hello', ' ', 'World')
Hello   World

Python 2.6+ 使用 print() 函数

from __future__ import print_function
>>> print('Hello', ' ', 'World')
Hello   World

2. Unicode

Python3.X 源码文件默认使用 utf-8 编码

这个应该算是 3.X 和 2.X 最大的差别了,意味着我们不用使用烦人的

# -*- encoding:utf-8 -*-

喜极而泣,奔走相告

Python2.X 有 ASCII str 类型,unicode() 是单独的,不是 byte 类型

Python3.X 中终有了 Unicode (utf-8) 字符串,以及一个字节类 bytebytearrays

也就是说,下面的代码是合法的,再也不会报 SyntaxError: invalid syntax 错误了

>>> 简单教程 = 'jiandanjiaocheng.com' 
>>>print(简单教程) 
jiandanjiaocheng.com

Python 2.x 使用 Unicode

Python2.x 中要使用 Unicode 必须在字符串前加 u 字符

>>> s = "简单教程,简单编程"
>>> s
'\xe7\xae\x80\xe5\x8d\x95\xe6\x95\x99\xe7\xa8\x8b,\xe7\xae\x80\xe5\x8d\x95\xe7\xbc\x96\xe7\xa8\x8b'
>>> s = u"简单教程,简单编程"
>>> s
u'\u7b80\u5355\u6559\u7a0b,\u7b80\u5355\u7f16\u7a0b'

Python 3.x

>>> s = "简单教程,简单编程"
>>> s
简单教程,简单编程

3. / 除法运算

Python 中的除法有两个运算符,///

Py2.x 中 / 除法跟我们在数学中学习的一样

  1. 如果除数和被除数都是整数,相除的结果是一个整数,把小数部分完全忽略掉( 不是四舍五入)
  2. 如果只要其中之一是浮点数,那么除法会保留小数点的部分得到一个浮点数的结果

Py3.x 中 / 除法的实现就差别大了,无论两个数是否是整数,都返回浮点数的结果

Py2.x

>>> 4 / 2
2
>>> 4.0 / 2.0
2.0

Py3.x

不管除数和被除数是否都是整数,返回的结果一定是浮点数

>>> 4/2
2.0

4. 对于 // 除法

// 叫做 floor 除法,俗称 地板流除法

// 除法会对除法的结果自动进行一个 math.floor() 操作,也就是向下取整

// 除法在 Py2.X 和 Py3.X 中效果是一致的

Py2.X

>>> -5 // 2
-3

Py3.X

>>> -5 // 2
-3

// 除法是并不是舍弃小数部分,而是执行 math.floor() 操作,如果要截取小数部分,可以使用 math.trunc() 函数

可以这么说,如果除法的结果都是正数,那么效果是一样的,如果是负数,那么效果就是天差地别了

>>> import math
>>> math.trunc(-5 / 2)
-2
>>> math.trunc(-5 / 3)
-3

5. 异常

  • Python 3.X 添加了 as 关键词来强化异常捕获的可读性

    Py2.X 中捕获异常一般如下

    except Exception, e
    

    Py3.X 中可以如下使用 as

    except Exception as e
    

    Py3.X 中还可以这样捕获多个异常

    except (Exception1, Exception2) as e
    

    可读性是否大大增强了,以前老是猜 e 到底是啥意思

    Python 2.6 已经支持 as 关键字了

  • Py3.X 中只有继承自 BaseException 及其子类的对象才可以被抛出

    Py2.x 时代,所有类型的对象都是可以被直接抛出的

  • Py2.x 时代,raise 语句使用逗号将抛出对象类型和参数分开

    Py3.x 取消了这种奇葩的写法,直接调用构造函数抛出对象即可

  • Py2.x 时代,异常在代码中除了表示程序错误,还经常做一些普通控制结构应该做的事情

    Py3.x 中则只有在错误发生的情况才能去用异常捕获语句来处理

6. xrange

Python 3.X 中废弃了 xrange,起而代之的是重新实现了 range() 完成同样的功能

可以这么理解, Py3.X 中更重视生成器模式,也就是所谓的惰性求值

Py2.X

Python 2 中 xrange() 创建迭代对象的用法是非常流行的,比如: for 循环或者是列表/集合/字典推导式

这个表现十分像生成器(比如 "惰性求值"),但是这个 xrange-iterable 是无穷的,意味着你可以无限遍历

由于它的惰性求值,如果只是需要其中少数几个元素,xrange() 函数 比 range() 更快 (如 for 循环 )

尽管如此,对比迭代一次,不建议重复迭代多次,因为生成器每次都从头开始

Py3.X

Python 3 中已经废弃了 xrange() 函数,起而代之的使用重新实现了 range() 函数

Python 3 中的 range() 函数也会惰性求值了,就像 Py2.X 中的那样

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 '\n\ntiming 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

7. 八进制字面量表示

  1. Py3.X 中 八进制数必须写成 0o777,原来的形式 0777 不能用了

    0 表示这是数值, o (小写) 其实是八进制 oct 的首字母,这其实是统一格式的要求

    python 2.x

    >>> 0o1000
    512
    >>> 01000
    512
    

    python 3.x

    >>> 01000
      File "<stdin>", line 1
        01000
            ^
    SyntaxError: invalid token
    >>> 0o1000
    512
    
  2. Py3.X 中二进制必须写成 0b111,原来的 b111 还能用,但不推荐了

    0 表示这是数值, b (小写) 其实是二进制 binary 的首字母

  3. Py3.X 新增了一个 bin() 函数用于将一个整数转换成二进制字串

上面说到的三点,其实 Python 2.6 就已经支持了

8. 不等运算符

Python 3.x 去掉了 <> 这种不等于号的写法,只保留了 != 这种写法

其实,Python 2.x 中不等于有两种写法 !=<>

9. 去掉了 repr 表达式 ``

Python 2.x 中反引号 (``) 相当于 repr() 函数的作用

Python 3.x 中去掉了反引号 (``) 这种写法,只允许使用 repr 函数

说不上好不好,但减少了运算符的数量倒是真的,不知道有多少人只记得 str(), 而不识 repr(),更不用说反引号了

10. 多个模块被改名 ( 根据 PEP8 )

根据 PEP8 PY3.X 对 2.X 中的多个模块进行了重新整理

  1. 改名

    旧的名字 新的名字
    _winreg winreg
    ConfigParser configparser
    copy_reg copyreg
    Queue queue
    SocketServer socketserver
    repr reprlib
  2. 合并

    1. StringIO 模块现在被合并到新的 io 模块内

      >>> import io
      >>> so = io.StringIO()
      >>>
      

      Python 2.6 已经支援新的 io 模块,所以只能算是移除了 StringIO 模块

    2. new, md5, gopherlib等模块被删除

      所有和 hash 相关的方法都已经移到 hashlib 了

      >> import hashlib
      >>> hashlib.new
      <function __hash_new at 0x10dcd5ea0>
      >>> hashlib.md5()
      <md5 HASH object @ 0x10dfc7a30>
      

      Python 2.6 已经支援 hashlib 模块,所以只能算是移除这些模块了

    3. httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib 被合并到 http 包内

      这个还真是合并了,因为 2.X 系列根本没有 http 包

    4. 取消了 exec 语句,只剩下 exec() 函数

      其实 Python 2.6 已经支持 exec() 函数

11. 数据类型

  1. Py3.X 去除了 long 类型,现在只有一种整型 ( int ),它的行为就像 2.X 版本的 long

    前面我们介绍过, long 其实是 long int ,也就是说 long 类型可以囊括 int 类型

    所以我们还可以这么理解,Py3.X 去除了 int 类型,然后把 long 重命名为 int

  2. 新增了 bytes 类型,对应于 2.X 版本的 八位串

    下面的代码定义了一个简单的 bytes 字面量

    >>> 
    >>> b = b'Hello'
    >>> b
    b'Hello'
    >>> type(b)
    <class 'bytes'>
    

    也就是我们在一个字符串前加上 b 就定义了一个 bytes 类型字面量

    str 对象和 bytes 对象可以使用 .encode() ( str -> bytes ) or .decode() ( bytes -> str ) 方法相互转化

    >>> b = b'Hello'
    >>> b
    b'Hello'
    >>> type(b)
    <class 'bytes'>
    >>> s = b.decode()
    >>> s
    'Hello'
    >>> type(s)
    <class 'str'>
    >>> b1 = s.encode()
    >>> b1
    b'Hello'
    >>> type(b1)
    <class 'bytes'>
    >>>
    
  3. 字典 ( dict ) 的 .keys().items().values()方法返回迭代器

    而之前的 iterkeys() 等函数都被废弃

    同时去掉的还有 dict.has_key(),用 in 替代它吧

Python2 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.