python2与python3的区别

一.性能

python3.x 起始比python2.x 效率低, 但是3.x后有极大的优化空间, 性能上正在追赶.

二.编码

Python3 对Unicode字符的原生支持.

python2中使用ASCII码作为默认的编码方式, string有两种类型: str 和 unicode. python3 只支持unicode的string.

Python2 Python3 表现形式 转换 作用
unicode str 字节 decode 显示
str bytes 字节 encode 存储, 传输
1
2
3
4
5
6
7
8
9
10
11
12
# python2:
>>> 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'>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# python3:
>>> print('strings are now utf-8 \u03BCnico\u0394é!')
strings are now utf-8 μnicoΔé!
>>> print(type('strings are now utf-8 \u03BCnico\u0394é!'))
<class 'str'>

>>> print('python3 has', type(b' bytes for storing data'))
python3 has <class 'bytes'>

>>> print(' also has', type(bytearray(b'bytearrays')))
also has <class 'bytearray'>

>>> 'note that we cannot add a string' + b'bytes for data'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be str, not bytes

python3默认使用utf-8编码, 使得变量名更加广泛.

1
2
3
>>> 中国 = 'china' 
>>>print(中国)
china
1
2
3
4
5
6
7
8
9
10
11
12
# python2.x
>>> str = "我爱北京天安门"
>>> str
'\xe6\x88\x91\xe7\x88\xb1\xe5\x8c\x97\xe4\xba\xac\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8'
>>> str = u"我爱北京天安门"
>>> str
u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8'

# python3.x
>>> str = "我爱北京天安门"
>>> str
'我爱北京天安门'

三.语法

1. 去除了 <> , 改用 !=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# python2:
>>> 1 <> 2
True
>>> 1 != 2
True

# python3:
>>> 1 <> 2
File "<stdin>", line 1
1 <> 2
^
SyntaxError: invalid syntax
>>> 1 != 2
True

2. 加入了 as 和 with关键字, 还有 True, False, None

True 和 False 在 Python2 中是两个全局变量(名字),在数值上分别对应 1 和 0,既然是变量,那么他们就可以指向其它对象,例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> True = False
>>> True
False
>>> True is False
True
>>> False = "a"
>>> False
'a'
>>> if False:
... print "false is True"
...
false is True

上面的代码违背了 Python 的设计哲学 Explicit is better than implicit.。而 Python3 修正了这个缺陷,True 和 False 变为两个关键字,永远指向两个固定的对象,不允许再被重新赋值。

1
2
3
>>> True = False
File "<stdin>", line 1
SyntaxError: can't assign to keyword

3. 整型触发返回浮点数, 整除使用 //

在python 2.x中/除法就跟我们熟悉的大多数语言,比如Java啊C啊差不多,整数相除的结果是一个整数,把小数部分完全忽略掉,浮点数除法会保留小数点的部分得到一个浮点数的结果。

在python 3.x中/除法不再这么做了,对于整数之间的相除,结果也会是浮点数。

1
2
3
4
5
6
7
8
9
10
11
# python2:
>>> 5/3
1
>>> 5.0/3
1.6666666666666667

# python3:
>>> 5/3
1.6666666666666667
>>> 5.0/3
1.6666666666666667

对于//除法(floor除法),会对除法的结果自动进行一个floor操作,在python 2.x和python 3.x中是一致的。

3. 加入nonlocal 语句

在python2中,函数里面可以使用关键字global 声明某个变量为全局变量, 但是在嵌套函数中, 如果要把一个变量声明为非局部变量是没有办法实现的. 在python3中,加入了关键字nonlocal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def func():
a = 1
def inner():
a = 11
inner()
print(a)
func()
# 1

def funcNonlocal():
a = 1
def inner():
nonlocal a
a = 11
inner()
print(a)
funcNonlocal()
# 11

4. 去除print语句, 加入print()函数

在python2中print是一条语句, 而在python3中是作为函数存在.

1
2
3
4
5
# 2:
print("python2")

# 3:
print("python3")

上述代码在输出结果上是一样的, 但是在Python2中是把(“python2”)当做是一个整体, 而后者print()是接收”python3”字符串作为参数的函数.

1
2
3
4
5
6
7
8
9
10
11
# python2:
>>> print("a")
a
>>> print("a","b")
('a', 'b')

# python3:
>>> print("a")
a
>>> print("a","b")
a b

由上述代码可以看出, 在python2中, print语句后面接的是一个元组对象. 相比较而言, 在python3中, print函数可以接受任意个位置参数. 如果想要在python2中把print当做函数使用, 可以导入future模块中的print_function.

1
2
3
4
5
6
7
8
9
# python2:
>>> print("a")
a
>>> print("a","b")
('a', 'b')

>>> from __future__ import print_function
>>> print("a","b")
a b

5. 去除raw_input , 加入input函数

在 Python 3 中已经解决了把用户的输入存储为一个 str 对象的问题。

6. 新的super(), 可以不给super()传参

1
2
3
4
5
6
7
class A(object):
def __init__(self, a):
print("A", a)

class B(A):
def __init__(self, a):
super().__init__(a)

7. 改变了顺序操作符的行为

例如: x < y , 当x和y的类型不匹配时抛出TypeError ,而不是返回随机的bool值.

1
2
3
4
5
6
7
8
9
# python2:
>>> 2 < "a"
True

# python3:
>>> 2 < "a"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'

8. 新式的八进制变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# python2:
>>> 0666
438
>>> 0777
511

# python3:
>>> 0666
File "<stdin>", line 1
0666
^
SyntaxError: invalid token
>>> 0o666
438
>>> 0o777
511

9. 字符串和字节串

在python2中:
字符串以 8-bit 字符串存储;

在python3中:
字符串以 16-bit Unicode 字符串存储;
现在字符串只有str 一种类型.

10. 数据类型

pthon3.x 去除了long类型, 只有一种整型—-int
python3 彻底废弃了 long+int 双整数实现的方法, 统一为 int , 支持高精度整数运算.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
# python2:
>>> a = b"china"
>>> a
'china'
>>> type(a)
<type 'str'>

# python3:
>>> a = b"china"
>>> a
b'china'
>>> type(a)
<class 'bytes'>

str对象和bytes对象可以使用 .encode() 将str 转换为 bytes, 或者使用 .decode() 将 bytes装换为str.

11. 面向对象

引入抽象基类

12. 异常

  • 所有异常都从BaseException 继承, 并删除了 StandardError

  • python2:

    1
    2
    3
    4
    try:
    pass
    except Exception, e:
    pass

    python3:

    1
    2
    3
    4
    try:
    pass
    except Exception as e:
    pass

13. 返回可迭代对象

python2中很多返回列表对象的内置函数和方法, 在python3中都改为了返回类似于迭代器的对象(可迭代对象), 由于迭代器的惰性加载特性使得操作大数据时可以更加有效率. 比如python2中的range和xrange函数合成了 python3中的range(同时兼容2和3).

1
2
3
4
5
# python2:
print range(3)
print type(range(3))
# [0, 1, 2]
# < type ‘list’>
1
2
3
4
5
6
7
# python3:
print(range(3))
print(type(range(3)))
print(list(range(3)))
# range(0, 3)
# < class ‘range’>
# [0, 1, 2]

除此, 字典对象的 dict.keys() , dict.values() , dict.items() 方法都不再返回列表, 而是以一个类似迭代器的 “view” 对象返回.
高阶函数map, filter, zip 返回的也都 不是列表对象了. 在python2中的迭代器必须实现 next 方法, 而在Python3 改成了 __next__.

14. for循环变量和去全局命名空间泄露

在python3 中 for循环变量不会导致命名空间泄露.

1
2
3
4
5
6
7
8
9
# python2:
i = 1
print 'before: i =', i
print 'comprehension: ', [i for i in range(5)]
print 'after: i =', i

# before: i = 1
# comprehension: [0, 1, 2, 3, 4]
# after: i = 4
1
2
3
4
5
6
7
8
9
# python3:
i = 1
print('before: i =', i)
print('comprehension:', [i for i in range(5)])
print('after: i =', i)

# before: i = 1
# comprehension: [0, 1, 2, 3, 4]
# after: i = 1

参考:
Python 2 和 Python 3 有哪些主要区别?
Python 2.7.x 与 Python 3.x 的主要差异
What’s New In Python 3.0
菜鸟教程