python2
# 查看python版本号
import platform
print(platform.python_version())
2.7.16 3.7.4
# 获取版本号
import platform
print(platform.python_version())
1. print/exec
结论:python3中print和exec为函数,必须使用括号
print 'Hello, World!'
exec 'print("Hello, World!")'
Hello, World! Hello, World!
print('Hello, World!')
exec('print("Hello, World!")')
Hello, World! Hello, World!
2. 编码
结论: python的默认编码改为utf-8,而python2的默认编码为ascii。
所以通常我们在编写包含非英文字符时,需要在python文件开头加上 # encoding: utf-8。
而在python3中就不需要这样的操作了。
但是实际使用中一般还是习惯性加上,因为不清楚代码是否有时需要在python2上执行。
import sys
print(sys.getdefaultencoding())
ascii
import sys
print(sys.getdefaultencoding())
utf-8
3. 除法
结论:python2中“/”默认是浮点除法,而python2中除法对整型是“地板除”,对浮点数据为“浮点除”。
print 1/2
print 1.0/2
0 0.5
print(1/2)
print(1.0/2)
0.5
0.5
4. 删掉的语法
cmp、<>不等号、xrange(其实就是range)、不再有经典类
# cmp
print cmp(1,2), cmp(1, 1), cmp(2,1)
# <> 不等号
print 1<>2
# xrange
print xrange(3)
# 经典类与新式类
class A:
pass
class B(object):
pass
a, b = A(), B()
print('a={}, b={}'.format(a, b))
print('a.__class__={}, b.__class__={}'.format(a.__class__, b.__class__))
print('type(a)={}, type(b)={}'.format(type(a), type(b)))
-1 0 1 True xrange(3) a=<__main__.A instance at 0x1082c06c8>, b=<__main__.B object at 0x1082bdc90> a.__class__=__main__.A, b.__class__=<class '__main__.B'> type(a)=<type 'instance'>, type(b)=<class '__main__.B'>
5. 抛出和捕获异常
结论: python3中抛出的和捕获的异常都是采用面向对象的构造函数的方式,避免了python2中奇葩的方式
A = 'Not Allow'
try:
if 'Not Allow' == A:
raise ValueError, A
except ValueError, e:
print(e)
Not Allow
A = 'Not Allow'
try:
if 'Not Allow' == A:
raise ValueError(A)
except ValueError as e:
print(e)
Not Allow
6. int与long
print(type(int(1)))
print(type(long(1)))
<type 'int'> <type 'long'>
print(type(int(1)))
print(int(12345678901234567890))
print(type(long(1)))
<class 'int'> 12345678901234567890
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-15-bdcf0920f30d> in <module> 1 print(type(int(1))) 2 print(int(12345678901234567890)) ----> 3 print(type(long(1))) NameError: name 'long' is not defined
7. True与False
结论:在python3中True和False都是关键字,不能被赋值。 而python2中可以被赋值修改
True = '123'
print(True)
123
True = '123'
File "<ipython-input-16-39e10140ed83>", line 1 True = '123' ^ SyntaxError: can't assign to keyword
8. 迭代对象
结论: python3中将map,filter,dict.items(), dict.keys(), dict.values的返回值改为迭代对象
b = [1,2,3,4,5]
# map函数返回迭代对象
it_map = map(lambda x:x**2, b)
print(it_map)
# filter函数返回迭代对象
it_filter = filter(lambda x:x>2, b)
print(it_filter)
# 词典函数返回迭代对象
a = {1:'hello', 2:'python'}
print(a.items())
print(a.keys())
print(a.values())
[1, 4, 9, 16, 25] [3, 4, 5] [(1, 'hello'), (2, 'python')] [1, 2] ['hello', 'python']
b = [1,2,3,4,5]
# map函数返回迭代对象
it_map = map(lambda x:x**2, b)
print(it_map)
for x in it_map:
print(x,)
# filter函数返回迭代对象
it_filter = filter(lambda x:x>2, b)
print(it_filter)
for x in it_filter:
print(x)
# 词典函数返回迭代对象
a = {1:'hello', 2:'python'}
for k,v in a.items():
print('k={}, v={}'.format(k, v))
for k in a.keys():
print('k={}'.format(k))
for v in a.values():
print('v={}'.format(v))
<map object at 0x105f10a90> 1 4 9 16 25 <filter object at 0x105f10950> 3 4 5 k=1, v=hello k=2, v=python k=1 k=2 v=hello v=python
9. 新增关键字
nonlocal、yield from、async/await、yield for
a = 12
def func():
a = 1
def func_in():
global a; # global关键字只能用于对全局空间中的声明
a = 2
func_in()
print('local a = ', a)
func()
print('global, a = ', a)
('local a = ', 1) ('global, a = ', 2)
# 这里只演示一下nonlocal的用法,其他关键字一般不会用到
def func():
a = 1
def func_in():
nonlocal a; # nonlocal关键字可以用对局部空间中的声明
a = 2
func_in()
print('local a = ', a)
func()
local a = 2
10. input与raw_input()
结论:python3中input()函数实现python2中raw_input()函数的功能。 python3中移除了raw_input()函数。
a = input()
print('type(a)={}, a={}'.format(type(a), a))
a = raw_input()
print('type(a)={}, a={}'.format(type(a), a))
123 type(a)=<type 'int'>, a=123 123 type(a)=<type 'str'>, a=123
a = input()
print('type(a)={}, a={}'.format(type(a), a))
a = raw_input()
123
type(a)=<class 'str'>, a=123
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-1-cb01db45b25f> in <module> 1 a = input() 2 print('type(a)={}, a={}'.format(type(a), a)) ----> 3 a = raw_input() NameError: name 'raw_input' is not defined
另外知乎上有个帖子作了如下总结,可供参考:
- 统一了字符编码支持。我特意把它拿出来放在第一条...
- 增加了新的语法。print/exec等成为了函数,格式化字符串变量,类型标注,添加了nonlocal、yield from、async/await、yield for关键词和annotations、context、traceback、qualname等dunder方法。
- 修改了一些语法。metaclass,raise、map、filter以及dict的items/keys/values方法返回迭代对象而不是列表,描述符协议,保存类属性定义顺序,保存关键字参数顺序
- 去掉了一些语法。cmp、<>(也就是!=)、xrange(其实就是range)、不再有经典类
- 增加一些新的模块。concurrent.futures、venv、unittest.mock、asyncio、selectors、typing等
- 修改了一些模块。主要是对模块添加函数/类/方法(如functools.lru_cache、threading.Barrier)或者参数。
- 模块改名。把一些相关的模块放进同一个包里面(如httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib放进了http里面,urllib, urllib2, urlparse, robotparse放进了urllib里面),个例如SocketServer改成了socketserver,Queue改成queue等
- 去掉了一些模块或者函数。gopherlib、md5、contextlib.nested、inspect.getmoduleinfo等。去掉的内容的原因主要是2点:1. 过时的技术产物,已经没什么人在用了;2. 出现了新的替代产物后者被证明存在意义不大。理论上对于开发者影响很小。
- 优化。重新实现了dict可以减少20%-25%的内存使用;提升pickle序列化和反序列化的效率;collections.OrderedDict改用C实现;通过os.scandir对glob模块中的glob()及iglob()进行优化,使得它们现在大概快了3-6倍等.. 这些都是喜大普奔的好消息,同样开发者不需要感知,默默的就会让结果变得更好。
- 其他。构建过程、C的API、安全性等方面的修改,通常对于开发者不需要关心。