注:本文的原文地址为
Key differences between Python 2.7.x and Python 3.x

许多 Python 初学者想知道他们应该从 Python 的哪个版本开始学习。对于这个问题我的答案是 “你学习你喜欢的教程的版本,然后检查他们之间的不同。"

但是如果你开始一个新项目,并且有选择权?我想说的是目前没有对错,只要你计划使用的库 Python 2.7.x 和 Python 3.x 双方都支持的话。尽管如此,当在编写它们中的任何一个的代码,或者是你计划移植你的项目的时候,是非常值得看看这两个主要流行的 Python 版本之间的差别的,以便避免常见的陷阱,

章节

  • 使用 __future__ 模块
  • print 函数
  • Integer division
  • Unicode
  • xrange
  • Raising exceptions
  • Handling exceptions
  • next() 函数 和 .next() 方法
  • For 循环变量和全局命名空间泄漏
  • 比较不可排序类型
  • 通过 input() 解析用户的输入
  • 返回可迭代对象,而不是列表
  • 更多的关于 Python 2 和 Python 3 的文章

future 模块

Python 3.x 介绍的 一些Python 2 不兼容的关键字和特性可以通过在 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 227: Statically Nested Scopes
generators 2.2.0a1 2.3 PEP 255: Simple Generators
division 2.2.0a2 3.0 PEP 238: Changing the Division Operator
absolute_import 2.5.0a1 3.0 PEP 328: Imports: Multi-Line and Absolute/Relative
with_statement 2.5.0a1 2.6 PEP 343: The “with” Statement
print_function 2.6.0a2 3.0 PEP 3105: Make print a function
unicode_literals 2.6.0a2 3.0 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)/2 或 3/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) 字符串,以及一个字节类:byte 和 bytearrays

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 \u03BCnico\u0394é!') 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 '\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

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

转:python2.x 和 python3.x的区别的更多相关文章

  1. python2.x和python3.x的区别

    一.python2.x和python3.x中raw_input( )和input( )区别 1.在Python2.x中raw_input( )和input( ),两个函数都存在,其中区别为 raw_i ...

  2. 【python系列】python2.x和python3.x的区别

    刚接触python使用的是python2.x的书籍,但是发现python3.x和python2.x有不小的区别,以下做一些记录 性能 Py3.0运行 pystone benchmark的速度比Py2. ...

  3. Python第一天:python2.x和python3.x的区别

    查看Python版本 # python -V Python2.7.5是centos7中默认安装的Python [root@localhost ~]# python -V Python [root@lo ...

  4. Python2.x与Python3.x的区别

    这个星期开始学习Python了,因为看的书都是基于Python2.x,而且我安装的是Python3.1,所以书上写的地方好多都不适用于Python3.1,特意在Google上search了一下3.x和 ...

  5. python2.x 与 python3.x的区别

    从语言的源码角度: python2.x 的源码书写不够规范,且源码有重复,代码的复用率不高; python3.x 的源码清晰.优美.简单 从语言的特性角度: python2.x 默认为ASCII字符编 ...

  6. python面试题Python2.x和Python3.x的区别

    所属网站分类: 面试经典 > python 作者:外星人入侵 原文链接: http://www.pythonheidong.com/blog/article/22/ 来源:python黑洞网 w ...

  7. python之路-python2.x与python3.x区别

    Python崇尚优美.清晰.简单,是一个优秀并广泛使用的语言. Python2.x 与 Python3.x的区别: python2.x:源码混乱,重复代码较多,冗余. python3.x:源码规范,崇 ...

  8. Python语言基础-语法特点、保留字与标识符、变量、基本数据类型、运算符、基本输入输出、Python2.X与Python3.X区别

    Python语言基础 1.Python语法特点 注释: 单行注释:# #注释单行注释分为两种情况,例:第一种#用于计算bim数值bim=weight/(height*height)第二种:bim=we ...

  9. 在Windows下同时安装Python2.x和Python3.x

    前言: Python现在是两个版本共存,Python2.x和Python3.x都同时在更新.但是Python2.x和Python3.x的区别还是很多的(以后我可能会写一篇文章列举一下Python2.x ...

随机推荐

  1. 高可用的K8S集群部署方案

    涉及到的内容 LVS HAProxy Harbor etcd Kubernetes (Master Worker) 整体拓补图 以上是最小生产可用的整体拓补图(相关节点根据需要进行增加,但不能减少) ...

  2. JS-DOM ~ 02. 隐藏二维码、锁定、获取输入框焦点、for循环为文本赋值、筛选条件、全选和反选、属性的方法操作、节点的层次结构、nodeType

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. CentOS 7 下网络无法访问 Failed to start LSB: Bring up/.

    [root@localhost Desktop]# ping 192.168.2.1PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.64 byt ...

  4. 微信小程序集成腾讯云 IM SDK

    微信小程序集成腾讯云 IM SDK 1.背景 因业务功能需求需要接入IM(即时聊天)功能,一开始想到的是使用 WebSocket 来实现这个功能,然天意捉弄(哈哈)服务器版本太低不支持 wx 协议(也 ...

  5. elk安装和使用

    elk安装和使用 使用的版本都是5.2.0 elasticsearch-5.2.0安装 在官网 下载 elasticsearch tar包 解压安装 tar zxf elasticsearch-5.2 ...

  6. 大数据平台搭建 - cdh5.11.1 - hbase集群搭建

    一.简介 HBase是一种构建在HDFS之上的分布式.面向列的存储系统.在需要实时读写.随机访问超大规模数据集时,可以使用HBase. 尽管已经有许多数据存储和访问的策略和实现方法,但事实上大多数解决 ...

  7. Elastic-Job:动态添加任务,支持动态分片

    多情只有春庭月,犹为离人照落花. 概述 因项目中使用到定时任务,且服务部署多实例,因此需要解决定时任务重复执行的问题.即在同一时间点,每一个定时任务只在一个节点上执行.常见的开源方案,如 elasti ...

  8. ACM讲课之字符串

    本次讲课讲全面介绍字符串以及如何使用字符串解决具体问题. 一.什么是字符串 1.如何存储字符串 平时我们使用的变量有很多,int代表整型变量,double代表浮点型变量,char代表字符型变量,那么对 ...

  9. iOS 13 正式发布,来看看有哪些 API 变动

    iOS 13 已正式发布,网上对其用户体验上的新特性的描述也很多.对于开发来说,需要关注的另一方面是新系统在 API 层面做了哪些改动,从而会对我们现有的代码产生什么影响. 在这里,我们基于 iOS ...

  10. Xshell无法连接到虚拟机Linux系统(桥接方式)

    一.  查看主机上网网卡网络配置信息 1.  查看本机所用网卡名称(适用于win10系统) 操作步骤: 1)  状态栏右键“WiFi连接图标” 2)  点击“打开“网络和Internet”设置” 3) ...