Python2x和3x主要差异总结Word文档格式.docx
《Python2x和3x主要差异总结Word文档格式.docx》由会员分享,可在线阅读,更多相关《Python2x和3x主要差异总结Word文档格式.docx(18页珍藏版)》请在冰点文库上搜索。
File"
<
stdin>
"
line1
01000
^
SyntaxError:
invalidtoken
运算符
(1)不等于测试
Python2.x中不等于有两种写法!
=和<
Python3.x中去掉了<
只有!
=一种写法,还好,我从来没有使用<
的习惯
(2)去掉了repr表达式``
Python2.x中反引号``相当于repr函数的作用
Python3.x中去掉了``这种写法,只允许使用repr函数,这样做的目的是为了使代码看上去更清晰么?
不过我感觉用repr的机会很少,一般只在debug的时候才用,多数时候还是用str函数来用字符串描述对象。
(3)除法运算
Python中的除法较其它语言显得非常高端,有套很复杂的规则。
Python中的除法有两个运算符,/和//
首先来说/除法:
在python2.x中/除法就跟我们熟悉的大多数语言,比如Java啊C啊差不多,整数相除的结果是一个整数,把小数部分完全忽略掉,浮点数除法会保留小数点的部分得到一个浮点数的结果。
在python3.x中/除法不再这么做了,对于整数之间的相除,结果也会是浮点数。
Python2.x:
1/2
1.0/2.0
0.5
Python3.x:
1/2
而对于//除法,这种除法叫做floor除法,会对除法的结果自动进行一个floor操作,在python2.x和python3.x中是一致的。
python2.x:
-1//2
-1
python3.x:
注意的是并不是舍弃小数部分,而是执行floor操作,如果要截取小数部分,那么需要使用math模块的trunc函数
importmath
math.trunc(1/2)
math.trunc(-1/2)
(4)比较运算符
Python2.x中允许不同类型的对象进行比较,比如:
-1<
'
'
True
1>
False
Python3.x中则不允许这类不同类型之间含糊不清的比较:
Traceback(mostrecentcalllast):
line1,in<
module>
TypeError:
unorderabletypes:
int()>
str()
我觉着即使在2.x中也不应该使用这种含糊不清的比较,1>
返回了False,这个是基于什么判断的?
说不清楚。
语句
(1)print
这是应该算是最广为人知的一个差别了吧,Python2.x和Python3.x之间连HelloWorld都是不兼容的。
python2.x中print是语句
print>
filex,y
向打开的输出流file中输出x,y变量的值
在python3.x中这句要这么写
print(x,y,)
file参数定义的默认值是sys.stdout
(2)扩展序列解包
python中的序列赋值一直是这门语言宣传时候的一个亮点,能把一个序列解开进行赋值:
8
9
10
11
12
13
14
15
x,y=[1,2]
x
y
x,y=1,2
x,y=y,x
python3.x对这一功能更加进行了强化,支持扩展序列解包:
x,*y=1,2,3
[2,3]
内置集合类型
内置集合的差别主要体现在字典对象的几个视图方法上,keys\items和values,在2.x中这几个试图方法每次都是赤裸裸的返回一个新的列表,3.x对这种粗鲁的行为做了优化,返回的是迭代器对象。
另外原先字典对象有个has_key方法来判断key在字典中是否存在,这个方法实现的功能跟in运算符完全一样,因此在3.x就把这个方法给干掉了。
函数
(1)nonlocal作用域
在2.x的时代,Python只有两个作用域,模块里面的全局作用域和函数的局部作用域,但是随着在函数中定义函数的情况越来越多,比如装饰器、闭包等等,这里面就出现了内层函数引用外层函数变量的问题:
比如我要在内层函数修改外层函数的一个变量,在Python2.x的时代就会出现错误:
defout_function():
...
call_count=0
defin_function():
call_count+=1
returnin_function
...
out_function()()
line4,inin_function
UnboundLocalError:
localvariable'
call_count'
referencedbeforeassignment
但是在Python3.x中只要使用nonlocal关键字对变量进行修饰,就会自动去外层函数寻找变量:
nonlocalcall_count
call_count+=1
(2)Key-wordonly参数
前面我们说到print在Python3.x中是作为函数提供的。
print的参数设计是这样的:
print(*value,sep='
end='
\n'
)
如果了解Python参数的顺序规则,我们知道在Python2.x中,参数的顺序必须遵循以下规则去定义:
deffunction(一般参数or带默认值参数,*sequence,**dict)
而这个地方却允许先定义*sequence再去定义一般参数,这就是Python3.x所支持的key-wordonly的参数形式。
在一个*之后允许去定义一些参数,这些参数在函数调用的时候必须指定参数名称。
这样本质上其实就是在*sequence类型的参数之后固定写死了一个**dict,当然也可以在后面继续定义一个**dict:
deftest(*value,name,**dict):
但这样写就不对了deftest(*value,**dict,name)
(3)map、filter和reduce
这三个函数号称是函数式编程的代表。
在Python3.x和Python2.x中也有了很大的差异。
首先我们先简单的在Python2.x的交互下输入map和filter,看到它们两者的类型是built-infunction:
map
built-infunctionmap>
filter
built-infunctionfilter>
它们输出的结果类型都是列表:
map(lambdax:
x*2,[1,2,3])
[2,4,6]
filter(lambdax:
x%2==0,range(10))
[0,2,4,6,8]
但是在Python3.x中它们却不是这个样子了:
class'
map'
map(print,[1,2,3])
mapobjectat0xa6fd70c>
filter'
filterobjectat0xa6eeeac>
首先它们从函数变成了类,其次,它们的返回结果也从当初的列表成了一个可迭代的对象,我们尝试用next函数来进行手工迭代:
f=filter(lambdax:
next(f)
对于比较高端的reduce函数,它在Python3.x中已经不属于built-in了,被挪到functools模块当中。
模块
Python2.x和3.x模块之间的差别主要体现在相对导入这部分的规则上。
在Python2.x和3.x当中都是使用点号来指定在当前包下进行相对导入,但是在没有点号的情况下,Python2.x会以先相对再绝对的模块搜索顺序,3.x的顺序跟这个相反,默认是绝对的,缺少点号的时候,导入忽略包含包自身并在sys.path搜索路径上进行查找。
面向对象
(1)经典类和新式类
PythonOO最神奇的地方就是有两种类,经典类和新式类。
新式类跟经典类的差别主要是以下几点:
1.新式类对象可以直接通过__class__属性获取自身类型:
type
2.继承搜索的顺序发生了改变,经典类多继承属性搜索顺序:
先深入继承树左侧,再返回,开始找右侧;
新式类多继承属性搜索顺序:
先水平搜索,然后再向上移动
3.新式类增加了__slots__内置属性,可以把实例属性的种类锁定到__slots__规定的范围之中。
4.新式类增加了__getattribute__方法
Python2.x中默认都是经典类,只有显式继承了object才是新式类
Python3.x中默认都是新式类,不必显式的继承object
ClassicClass.__class__
AttributeError:
classClassicClasshasnoattribute'
__class__'
classNewClass(object):
pass
NewClass.__class__
type'
type'
classNewClass:
pass
(2)无绑定方法
在Python2.x中除了类方法和静态方法,其余的方法都必须在第一个参数传递self跟实例绑定,但是在Python3.x中废除了这条规定,允许方法不绑定实例,这样的方法跟普通的函数没有区别:
classMyClass:
deffunction():
print"
function"
MyClass.function()
unboundmethodfunction()mustbecalledwithMyClassinstanceasfirstargument(gotnothinginstead)
m=MyClass()
m.function()
function()takesnoarguments(1given)
print("
)
function
(3)重要的重载
1.next()和__next__():
这应该是继print之后第二大坑爹的不兼容吧,Python程序漫山遍野都是迭代器,但是2和3之间迭代器的实现接口方法名是不同的……嗯,啥都不说了。
2.分片拦截:
Python3.x之前,类可以定义__getslice__和__setslice__方法来专门拦截分片,并且这两个方法优先于__getitem__和__setitem__,但是Python3.x时代这俩方法再也不存在了,全部的工作都交给了__getitem__和__setitem__,因此在使用这两个方法之前要先判断传递进参数的类型是不是slice对象。
3.__bool__方法:
我们知道Python中默认将所有的空对象定义为布尔意义上的False,在自己定义的类中我们也可以加入自定义的布尔判断标准,在2.x中这个方法名叫做__nonzero__,这个名字显然非常不直观并且不科学!
所有考试交白卷的孩子我们都要否定他们的才能么?
显然不能!
因此Python3.x中这个方法被重名命为__bool__
4.3.x取消了用于大小比较的__cmp__方法,取而代之的是:
__lt__、__gt__、__le__、__ge__、__eq__、__ne__,嗯,我感觉这个想法真是不能苟同……有谁能说服我给我洗脑让我爱上这一堆__lt__、__gt__、__le__、__ge__、__eq__、__ne__么。
。
(4)类修饰器
在我的上一篇博客中秀了一把函数装饰器在表单验证中的使用,
在3.x的时代,类也有装饰器了,这个装饰器威力巨大,能把装饰的类搞的面目全非,总之想怎么搞就怎么搞,用法同函数装饰器基本一致,只不过传递的参数是类型:
defshutdown(cls):
defshutdown_func(self):
dosomething..."
cls.shutdown=shutdown_func
returncls
@shutdown
...classTest:
t=Test()
t.shutdown()
dosomething...
异常
先来看一段代码
classPerson:
def__init__(self,msg):
self.msg=msg
try:
raisePerson,"
woca"
...exceptPersonasp:
printp.msg
woca
16
17
18
raisePerson("
print(p.msg)
line2,in<
exceptionsmustderivefromBaseException
Duringhandlingoftheaboveexception,anotherexceptionoccurred:
line3,in<
catchingclassesthatdonotinheritfromBaseExceptionisnotallowed
接下来说不同:
1.在2.x时代,所有类型的对象都是可以被直接抛出的,在3.x时代,只有继承自BaseException的对象才可以被抛出。
2.2.xraise语句使用逗号将抛出对象类型和参数分开,3.x取消了这种奇葩的写法,直接调用构造函数抛出对象即可。
在2.x时代,异常在代码中除了表示程序错误,还经常做一些普通控制结构应该做的事情,在3.x中可以看出,设计者让异常变的更加专一,只有在错误发生的情况才能去用异常捕获语句来处理。
其它
(1)编码
Py3.X源码文件默认使用utf-8编码,不需要再在文件头上声明
#-*-coding:
utf-8-*-
(2)input函数
取消了蛋疼的raw_input,input函数的功能跟原先的raw_input一样
x=input("
pleaseinputx:
pleaseinputx"
pleaseinputx1
1'
(2)返回结果列表->
迭代器
取消了原先的xrange,现在range函数的返回结果同之前的xrange的返回结果一样,不是列表,而是一个可迭代的对象。
其它常用的内置函数,如zip也是如此。
(3)Unicode字符串
能很好的支持Unicode
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"
u'
\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8'
我爱北京天安门'
没有去考究核心库的差别,常用语法上的差别就总结了这些,感觉……还好吧,很多常用的框架现在都开始支持Python3.x,虽然现在自己主要是在用2.7进行开发,但多了解一下最新的动态总是好的,Python最初版本设计的年代距离现在已经很长时间了,貌似跟自己同岁,可能那时的一些概念尚不清晰,但Python出现的比Java早多了,能设计到这种先进地步,已经相当厉害,Pytho