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、安全性等方面的修改,通常對於開發者不需要關心。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章