Python3和Python2的对比

说来惭愧,Python3问世这么久,也没有认真学习一下,一直认为Python2够用了,而且很多的第三方库还是要求Python2版本的,兼容性还是很重要的考虑因素。但话是这么说,IT的人终究要顺应时代的发展的,不断学习新知识。

废话不多说,开始Python3的学习,主要是和Python2进行对比。

1、编码

首先说下为什么要编码。由于计算机只能处理数字,也就是说想要处理文本,必须将文本转换为相应的数字,这种将字符串转换为字节的实现过程就叫做编码。最早的编码方式是ASCII,用一个字节表示一个字符,因为计算机是国外发明的,他们只是考虑到字母,符号和数字,即‘A’的编码是65。
一个字节最大的范围是255.,拿到中国,中文用一个字节是不够的,因此相应出现了GB2312,GBK等等。类似地,其他的国家也有他们特定的编码方式。每个国家都有了自己的编码,你的东西拿到我这来可能就出现乱码,因为为了统一规划就出现了Unicode,通常用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。但是Unicode最大的缺点是当你对于可以用ASCII编码(即可以用一个字节表示)却使用了两个字节,大大浪费了空间,因此utf-8应运而生,它是一种边长的编码方式,字长可以是1到6个字节。 ASCII是utf8的一个自集,也就是说,当字符小于127的时候,就采用ASCII编码。

上面说了这么多的编码方式,再说下Python2和3的编码。

Python2的默认编码方式是ASCII。你可以通过sys.getdefaultencoding()查看。字符串类型共有两种:

  • str表示8位文本和二进制数据。
  • unicode用来表示宽字符Unicode文本(类似:u'海波'前面带有u前缀的)。
    print type('s')  #type('str')
    print type(u'我爱你') #type('unicode')
    

在Python3中,取消了这种区别,都用str表示字符串,且默认编码方式是utf-8。说实话,这真的是方便太多了。 Python3中字符串对象主要有:

  • str表示Unicode文本(8位的和更宽的);
  • bytes表示二进制数据;
  • bytearray,是一种可变的bytes类型。
    name = '我爱你'
    print(name)   #'我爱你'
    

str统一表示了Unicode的,避免了在Python2中经常会遇到的编码转换问题了。
bytes类型是是字符串前面加了一个'b',它的作用是如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。

    b'sfsf'   //<class 'bytes'>

以Unicode表示的str如果要转换为某个字节,可以选择某种编码方式,如utf8,ascii:

    name = '我爱你'
    print(name.encode('utf-8'))  #b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
    print('hai'.encode('ascii')) #b'hai'
    print(name.encode('ascii'))

    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

name是一个Unicode文本,如果要用ascii编码,就会报错,因为中文超过了ascii编码范围。

通常都是内存中使用Unicode,当需要保存在硬盘中或者传输时,将字符串编码为utf-8类型。在Python2中需要在文件头部加上#encoding:utf-8,单在Python3中不需要了,默认源文件的编码就是utf-8。

上面说到了str转换为bytes类型,那肯定会涉及到bytes到str类型转换,因为读取磁盘数据的过程就必须进行转换:b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'.decode('utf-8')。

细心的你可能会遇到一个问题,为什么Python2中没有bytes类型呢?这是因为str充当了这一角色。

说了这么说,我认为最牛逼,牛逼的一个用法就要出现了:

因为统一都用Unicode文本,因此函数可以用非ascii命名:

    def 海波():
        print('test')

    海波()  #test

这真是让我感到了一阵惊喜!

2、print

在Python2中,print是一个语句;在Python3中print是一个函数,因此这就决定了两者使用方式是不同的:

python2:

    print 's'
    print('s')

python3:

    print('s')

没错,python只有这一种用法。看一下print源代码:

def print(*args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.
    """
    pass

看函数可以知道,print重定向也发生了改变。
python2中我们用“>>"进行重定向:

print >>file('s.txt','w'),'wfwf'

python3中:

print(x,y,file=f)

3、xrange

Python3中取消了xrange,range函数的作用和Python2中的xrange相同。且range函数多了一个 contains 方法,该方法可以加速数值的寻找(该方法在Python2中不存在):

    r = range(1000)
    100 in r

4、迭代器对象

一些函数或方法在Python2中会返回列表,如filter,map等等,但在Python3中它们默认返回的都是迭代器。这些函数包括:

zip;
filter;
map;
dictionary's .keys() method
dictionary's .values() method
dictionary's .items() method

如果想要使用列表的时候,直接用list转换一下就行。

5、reduce,apply,input

Python2中的reduce函数被移到到functools模块中了,用法还是一样。
apply函数在python3中被废除,直接就调用函数即可。
python3取消了raw_input,只有input。

6、类

python2中有新式类和旧式类之分,新式类要显示地用object表明;但在Python3中,统一为新式类。当然你可以加上object。

7、字典

在迭代器对象中已经说了,字典的keys(),values(),items()返回的是迭代器,因此python2中的itervalues,iteritems等方法就被废除了。此外字典的has_key方法也被取消了,直接用in。

8、异常

1、抛出异常

python2中抛出异常支持新旧两种标记,即加括号护着逗号相隔;在Python3中,如果不加括号就会抛出另外有一个异常,即语法错误:

Python2:
    raise ValueError,'valuerror
    raise ValueError('valuerror)

Python3:
    raise ValueError,'valuerror  #Syntax Error,invalid syntax
    raise ValueError('valuerror)

2、处理异常

处理异常也发生了变化,python3必须使用as。 Python2:

try:
    print 's'
except Exception,e:
    print 'error'

Python3:

try:
    print('s')
except Exception as e:
    print ('error')

3、异常对象

在Python 2下异常对象是可能迭代和索引的:

>>> e = Exception('arg1', 'arg2')
>>> e[1]'
arg2'
>>> for a in e:
...   print a
...
arg1
arg2

在Python 3下你必须要用args属性,这同样能在Python 2下工作。

>>> e = Exception('arg1', 'arg2')
>>> e.args[1]
'arg2'
>>> for a in e.args:
...   print a
...
arg1
arg2

9、整除

Python2:

3 / 2 = 1
3 // 2 = 1
3 / 2.0 = 1.5
3 // 2.0 = 1.0

python3:

3 / 2 = 1.5
3 // 2 = 1
3 / 2.0 = 1.5
3 // 2.0 = 1.0

10、function模块

Python 3.x 介绍的 一些Python 2 不兼容的关键字和特性可以通过在 Python 2 的内置 __future__ 模块导入。如果你计划让你的代码支持 Python 3.x,建议你使用 __future__ 模块导入。例如,如果我想要 在Python 2 中表现 Python 3.x 中的整除,我们可以通过如下导入

from __future__ import division
 print:
from __future__ import print_function

总结:Python3中的变化其实含有很多,后续会继续补充。感觉有些变化还是很给力的,尤其是编码,但一些变化我觉得有些牵强,我现在目前还是倾向于用2+。

--------EOF---------
微信分享/微信扫码阅读