Python 2與Python 3 的區別
信息安全公益宣傳,信息安全知識啟蒙。
教程列表見微信公眾號底部菜單
越來越多的庫要放棄Python 2了,開始轉向Python 3了。最近的項目開始用Python3寫了,也體會了一下2和3的區別。主要的一些區別在以下幾個方面:
print函數
整數相除
Unicode
異常處理
xrange
map函數
不支持has_key
print函數
Python 2中print是語句(statement),Python 3中print則變成了函數。在Python 3中調用print需要加上括弧,不加括弧會報SyntaxError
Python 2
print"hello world"
輸出
hello world
Python 3
print("hello world")
輸出
hello world
print"hello world"
輸出
File"", line1
print"hello world"
^
SyntaxError: Missing parenthesesincall to"print"
整數相除
在Python 2中,3/2的結果是整數,在Python 3中,結果則是浮點數
Python 2
print"3 / 2 =",3/2
print"3 / 2.0 =",3/2.0
輸出
3/2=1
3/2.0=1.5
Python 3
print("3 / 2 =",3/2)
print("3 / 2.0 =",3/2.0)
輸出
3/2=1.5
3/2.0=1.5
Unicode
Python 2有兩種字元串類型:str和unicode,Python 3中的字元串默認就是Unicode,Python 3中的str相當於Python 2中的unicode。
在Python 2中,如果代碼中包含非英文字元,需要在代碼文件的最開始聲明編碼,如下:
# -*- coding: utf-8 -*-
在Python 3中,默認的字元串就是Unicode,就省去了這個麻煩,下面的代碼在Python 3可以正常地運行。
a ="你好"
print(a)
異常處理
Python 2中捕獲異常一般用下面的語法
try:
1/
exceptZeroDivisionError, e:
printstr(e)
或者
try:
1/
exceptZeroDivisionErrorase:
printstr(e)
Python 3中不再支持前一種語法,必須使用as關鍵字。
xrange
Python 2中有 range 和 xrange 兩個方法。其區別在於,range返回一個list,在被調用的時候即返回整個序列;xrange返回一個iterator,在每次循環中生成序列的下一個數字。Python 3中不再支持 xrange 方法,Python 3中的 range 方法就相當於 Python 2中的 xrange 方法。
map函數
在Python 2中,map函數返回list,而在Python 3中,map函數返回iterator。
Python 2
map(lambdax: x+1, range(5))
輸出
[1,2,3,4,5]
Python 3
map(lambdax: x+1, range(5))
輸出
list(map(lambdax: x+1, range(5)))
輸出
[1,2,3,4,5]
filter函數在Python 2和Python 3中也是同樣的區別。
不支持has_key
Python 3中的字典不再支持has_key方法
Python 2
person = {"age":30,"name":"Xiao Wang"}
print"person has key "age": ", person.has_key("age")
print"person has key "age": ","age"inperson
輸出
person has key"age":True
person has key"age":True
Python 3
person = {"age":30,"name":"Xiao Wang"}
print("person has key "age": ","age"inperson)
輸出
person has key"age":True
print("person has key "age": ", person.has_key("age"))
輸出
Traceback (most recent call last):
File"", line1,in
AttributeError:"dict"object has no attribute"has_key"
print函數
在py2中print是一個語法結構,而在py3中print是一個函數,
print(value, ..., sep=" ", end="
",file=sys.stdout, flush=False)
file可以是文件,也就是可以把列印的東西直接輸出到文件,這個就很方便,我經常用。比如:
a = range(10)
out_file = open(「print_test_file.txt」, 『w』)
for x in a:
print(x,sep=』 『, end = 「
」, file=out_file)
編碼問題
在py2中,編碼問題是個大問題,可以單獨拉出來講一次。這裡簡單說一下,在py2中,把字元串分為Unicode和str兩種類型。
>>> s1 = "machine learning"
>>> type(s1)
>>> s2 = u"machine learning"
>>> type(s2)
>>> s3 = "中國"
>>> type(s3)
"xd6xd0xb9xfa"
>>> s4 = u"中國"
>>> type(s4)
py3中沒有Unicode,他們都是字元串
>>> s1 = "machine learning"
>>> type(s1)
>>> s2 = u"machine learning"
>>> type(s2)
>>> s3 = "中國"
>>> type(s3)
"中國"
當我們需要把py2中的unicode字元輸出到文件或者傳輸到網路上,需要先把unicode字元轉換為str類型,py2的encode方法就是編碼unicode字元到指定字元類型,因為py2默認編碼方式為unicode,所以當使用encode方式時,傳入的參數就是目標編碼格式,比如utf-8或者gbk等,當py2把一個字元存入到文件的時候,首先會判斷字元的類型,如果是str,則直接存入文件,如果是Unicode類型,則先要轉換為str類型,就需要encode方法,這時候默認的是ascii字元,然後ascii字元是不包括中文的,所以會引發UnicodeEncodeError。而decode是把str轉換為unicode字元,剛說了py2的默認格式是unicode,所以decode的時候,需要傳入的參數名字就是字元的現在的編碼的編碼方式,比如utf-8或者gbk,當傳入的參數名字不是現在編碼方式的時候,就會引發UnicodeDecodeError。
好了,這是py2中的坑,這些問題在py3中統統得到了解決。py3中沒有Unicode和str的區別,Unicode字元也會當做utf-8來看待,我們知道utf-8是包括中文的,所以當把中文字元存入文件的時候,就不會發生編碼問題。這也是為什麼當代碼中包括中文的時候,不需要在第一行顯式的指定編碼格式,# coding:utf-8.
除法問題
在py2中兩個整數除法的得到的是0,要得到浮點數,則除數或者被除數有一個是浮點數,而在py3中,整數相除可以得到浮點數。但是如果要在py3中整數相除也得到0的話,就要使用//,而不是/。
# python2
print 1/2
print 1/2.
# python3
print(1/2)
print(1//2)
nonlocal 語句
py3 新加入的,可以指定非全局變數。
輸入函數
在py2中輸入函數是raw_input和input兩個函數, 而py3中刪除了raw_inpus, 只使用input
I/O方法,xreadlines()
在py2中,一個文件對象有xreadlines()方法,返回一個迭代器,每次只讀取一行數據,可以使用for循環輸出結果。在py3中刪除了這個方法。
cPickle
py2中的cPickle被移除,py3中被pickle代替。
urllib
py2中存在兩個包,urllib和urllib2,是爬蟲經常用的模塊,py3中統一到了urllib中。並且py2中的urlparse模塊被統一到了urllib.parse模塊下。
包內的相對導入
這個挺重要的一個改變,需要掌握一下。在py2中,假設你寫了三個.py的模塊,比如:
--first.py
--second.py
--third.py
你想在3.py中導入1和2,可以直接
import first
import second
因為py2的解釋器會首先在當前目錄下搜索first和second,沒有找到才會去python的路徑中去找。而在py3中就不行,你需要這樣做
from . import first
from . import second
因為py3會直接在python 的路徑中去搜索,如果first.py和second.py在父目錄當中,則需要這樣
from .. import first
from .. import second
多加一個點,就這樣,是不是很簡單。
新式的8進位變數,修改了oct函數,oct是返回一個整形或者長整形的8進位數。
py2可以這樣
438
>>> oct(438)
『0666』
在py3中
SyntaxError: invalid token
438
>>> oct(438)
『0o666』
新的super方法,可以不傳參數
>>> class A(object):
def__init__(self, a):
print("A",a)
>>> class B(A):
def__init__(self, a):
super().__init__(a)
A 8
dict的.keys(),items(),values()方法返回一個迭代器,iterkeys(),has_key()廢棄。
python3引入抽象基類
Abstract Base Classes, ABCs
迭代器
迭代器的next()方法改名為__next__,增加了內置函數next()
增加裝飾器
@abstractmethod 和@anstractproperty兩個新裝飾器,編寫抽象方法更加方便。
移除了imageop,audiodev, Bastion, bsddb,bsddb185, exceptions,linuxaudiodev, md5, MimeWrite, mimify, popen2, rexec, sets, sha, strinold,strop, sunaudiodev, timing, xmlib, new模塊
這些是自帶的模塊,在py3中還移除了一些第三方模塊。
os模塊中的os.tmpnam()和os.tmpfile()移到tmpfile模塊中
http
在py2中相關的模塊由httplib,Cookie, cookielib, BaseHTTPServer, SimpleHTTPServer, CGIHttpServer,在py3中統一到了http模塊中,變成http.client,http.cookies, http.cookiejar, http.server.
urllib
py2中存在兩個包,urllib和urllib2,是爬蟲經常用的模塊,py3中統一到了urllib中。並且py2中的urlparse模塊被統一到了urllib.parse模塊下。
包內的相對導入
這個挺重要的一個改變,需要掌握一下。在py2中,假設你寫了三個.py的模塊,比如:
--first.py
--second.py
--third.py
你想在3.py中導入1和2,可以直接
import first
import second
因為py2的解釋器會首先在當前目錄下搜索first和second,沒有找到才會去python的路徑中去找。而在py3中就不行,你需要這樣做
from . import first
from . import second
因為py3會直接在python 的路徑中去搜索,如果first.py和second.py在父目錄當中,則需要這樣
from .. import first
from .. import second
多加一個點,就這樣,是不是很簡單。
GIF


※今晚20:30直播授課教學答題輔助
※Python-GUI Tkinter模塊
TAG:Python |