python3与python2常见区别

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

另外知乎上有个帖子作了如下总结,可供参考:

  1. 统一了字符编码支持。我特意把它拿出来放在第一条...
  2. 增加了新的语法。print/exec等成为了函数,格式化字符串变量,类型标注,添加了nonlocal、yield from、async/await、yield for关键词和annotationscontexttracebackqualname等dunder方法。
  3. 修改了一些语法。metaclass,raise、map、filter以及dict的items/keys/values方法返回迭代对象而不是列表,描述符协议,保存类属性定义顺序,保存关键字参数顺序
  4. 去掉了一些语法。cmp、<>(也就是!=)、xrange(其实就是range)、不再有经典类
  5. 增加一些新的模块。concurrent.futures、venv、unittest.mock、asyncio、selectors、typing等
  6. 修改了一些模块。主要是对模块添加函数/类/方法(如functools.lru_cache、threading.Barrier)或者参数。
  7. 模块改名。把一些相关的模块放进同一个包里面(如httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib放进了http里面,urllib, urllib2, urlparse, robotparse放进了urllib里面),个例如SocketServer改成了socketserver,Queue改成queue等
  8. 去掉了一些模块或者函数。gopherlib、md5、contextlib.nested、inspect.getmoduleinfo等。去掉的内容的原因主要是2点:1. 过时的技术产物,已经没什么人在用了;2. 出现了新的替代产物后者被证明存在意义不大。理论上对于开发者影响很小。
  9. 优化。重新实现了dict可以减少20%-25%的内存使用;提升pickle序列化和反序列化的效率;collections.OrderedDict改用C实现;通过os.scandir对glob模块中的glob()及iglob()进行优化,使得它们现在大概快了3-6倍等.. 这些都是喜大普奔的好消息,同样开发者不需要感知,默默的就会让结果变得更好。
  10. 其他。构建过程、C的API、安全性等方面的修改,通常对于开发者不需要关心。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章