谈谈python2与python3

1. __future__:

python每次更新时,引入了一些新的模块或功能,那么版本之间会可能会出现版本不兼容问题。

__future__ 模块就是为了解决这个问题,它把新功能添加到了这个模块中,可以使用这个模块,进行新功能的测试与使用。

例:

python2在没有导入包的情况下:

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

print('2019','12','6',sep='-',end='')

"""
运行结果:
  File "D:/python/ƽʱ����/test_future.py", line 17
    print('2019','12','6',sep='-',end='')
                             ^
SyntaxError: invalid syntax
"""

那么把导入包__future__取消注释:

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

print('2019','12','6',sep='-',end='')

"""
运行结果:

当前版本Python 2.7.14
2019-12-6
"""

python3下运行:

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

print('2019','12','6',sep='-',end='')

"""
运行结果:

当前版本Python 3.6.1
2019-12-6
"""

 

除了print_function外,还有其它功能如 division、absolute_import、with_statement等python3新功能,具体可以看官方文档:https://docs.python.org/2.7/library/__future__.html

 

2. 2to3

2to3是与当前Python版本发行的命令工具,该工具用于将Python2代码转换成Python3代码。

文件目录在:C:\mysoftware\Python\Python36\Tools\scripts  目录以自己安装而定

使用方式:

2to3 文件.py:用来说明文件中代码更变的说明信息。

2to3 -w 文件.py:将python2代码改为python3代码。

案例:

用python2写一个打印hello world! ,文件名为 py2to3_test.py

用python3执行并说明如下:

使用2to3 -w py2to3_test.py时,代码会发生改变:代码由python2变成了python3!!!

官方建议:只有在编写Python2代码并将其转换为Python3代码部署时才使用2to3。

其实想想,在实际,大多数项目中是不可以行的,毕竟项目中代码量大,使用2to3可能会增加负担。

 

3. six

是Python2与Python3之间兼容性库,提供了一些实用函数,消除Python版本之间的差异,而且在Python2与Python3两个版本中都能执行。

相比2to3,它只需要维护一份代码,同样的代码可以在两个版本中运行。

six从根本上完成的工作是为Python2与Python3之间变更的元素提供唯一接口。

案例:

在Python2中 str 表示字节型字符串,unicode 表示文本型字符串。而在Python中,bytes表示字节型字符串,str 表示文本型字符串。

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

print(type('hccfm'))
print(type(u'hccfm'))
print(type(b'hccfm'))
print(type(six.text_type('hccfm')))


"""
当前版本Python 2.7.14
<type 'str'>    # 字节型
<type 'unicode'>    #文本型
<type 'str'>    # 字节型
<type 'unicode'>    #文本型
"""

"""
当前版本Python 3.6.1
<class 'str'>   #文本型
<class 'str'>   #文本型
<class 'bytes'> # 字节型
<class 'str'>   #文本型
"""

通过上面例子可以看出,通过six.text_type() 不管在那个版本中,都是定义为文本型字符串,与之相反的为six.binary_type。

除了text_type外,还有其它好用的功能。具体去官网或看源码。直接拿来用就行了!!!

 

4. Python2与Python3的变更

4.1 字符串与unicode

同3案例说到,在Python2中 str 表示字节型字符串,unicode 表示文本型字符串。而在Python中,bytes表示字节型字符串,str 表示文本型字符串。

Python2:

在代码中,直接没任何声明的是字节型字符串,而文本型则需要在字符串前加上u

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


s = 'hccfm'
s1 = u'hccfm'

print(type(s))
print(type(s1))

"""
当前版本Python 2.7.14
<type 'str'>
<type 'unicode'>
"""

Python3:

在代码中,直接没任何声明的是文本型字符串,而字节型则需要在字符串前加上b

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


s = 'hccfm'
s1 = b'hccfm'

print(type(s))
print(type(s1))

"""
当前版本Python 3.6.1
<class 'str'>
<class 'bytes'>
"""

4.2 除法

在python2中,除法(/),在作用于两个整型数时,它是一个取整除法,会导致数据在混淆。如5/2=2 ,而不是5/2=2.5,它了避免这一点,在python2中,要想得到正确的结果,则使除数或者被除数为float类型。如5.0/2=2.5

在python3中,则解决这个问题,新添加了取整除法(//)功能。

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


print(4/2)
print(5/2)
print(5.0/2)

"""
当前版本Python 2.7.14
2
2
2.5
"""

4.3 模块的导入

在python2中,在导入模块时,是先相对导入再绝对导入。也就是说,当代码出现模块导入时,它会先在同一个目录中寻找,如果找到,则完成。如果没有找到,则从sys.path中所有的目录中查找一个匹配的模块,正常情况下,会包含所有已经安装的Python包。

该行为可能导致问题,例如,仅仅是在一个目录中添加重复命名的模块会导致该目录中的其他模块失效,因为突然开始执行相对导入而不是绝对导入。

在python3中,所有导入都是绝对导入,如果想要相对导入,则使用特殊的语法,使用英文句号(.)作为开头,如 import .foo

一个英文句号(.)表示同一级目录下,两个英文句号(..)表示上级目录。

由于两个版本不一,为了解决这个问题可以使用 __future__模块下在absolute_import

from __future__ import absolute_import

4.4 “老式风格” 类的移除

看例子说明:

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform



import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


class foo:
    pass

class foo1(object):
    pass

print(type(foo))
print(type(foo1))


"""
当前版本Python 2.7.14
<type 'classobj'>
<type 'type'>
"""

"""
当前版本Python 3.6.1
<class 'type'>
<class 'type'>
"""

Python2中,在创建一个类时,没有显示的说明继承,则会使用老式风格的类。

Python3中,则移除了老式风格类的继承。

如果想在python2与python3中都能执行,那个显示的继承object这个类就行。

 

4.5 元类

python2中,创建一个元类,则给属性 __metaclass__ 赋值无类即可。

class foo:
    __metaclass__ = 元类

python3中,创建一个无类,则需要在类中进行声明。

class foo1(object,metaclass=元类):
    pass

 

4.6 异常语法

  • 异常处理:
# python2
try:
    raise ValueError('...')
except ValueError , e:
    print(e)

# python3
try:
    raise ValueError('...')
except ValueError as e:
    print(e)

python3把python2中的英文逗号(,) 改为as 

 

  • 异常链:

在python代码中,在解释器处理一个异常时(在except子句中),引发了另一个异常。python2中,所有关于原始异常的信息会丢失,不这利于异常的处理。而在python3中,当触发第二次异常时,将会把原始异常赋给__context__属性。此外,python3还可以显示的指定别一个异常,通过语法: raise  from 指定。

案例1:python2运行原始异常丢失!!!

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


try:
    3/0
except ZeroDivisionError as e:
    raise ValueError('此处触发一个ValueError')


"""
当前版本Python 2.7.14
Traceback (most recent call last):
  File "D:/python/ƽʱ����/test_future.py", line 24, in <module>
    raise ValueError('此处触发一个ValueError')
ValueError: 此处触发一个ValueError
"""

案例2:python3运行原始异常保留。

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


try:
    3/0
except ZeroDivisionError as e:
    raise ValueError('此处触发一个ValueError')


"""
当前版本Python 3.6.1
Traceback (most recent call last):
  File "D:/python/平时代码/test_future.py", line 19, in <module>
    3/0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/python/平时代码/test_future.py", line 21, in <module>
    raise ValueError('此处触发一个ValueError')
ValueError: 此处触发一个ValueError
"""

案例3:python3显示指定异常

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


try:
    3/0
except ZeroDivisionError as e:
    raise ValueError('此处触发一个ValueError') from e


"""
当前版本Python 3.6.1
Traceback (most recent call last):
  File "D:/python/平时代码/test_future.py", line 19, in <module>
    3/0
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:/python/平时代码/test_future.py", line 21, in <module>
    raise ValueError('此处触发一个ValueError') from e
ValueError: 此处触发一个ValueError
"""

案例4:python3中,禁止异常关联,使用None

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))


try:
    3/0
except ZeroDivisionError as e:
    raise ValueError('此处触发一个ValueError') from None


"""
当前版本Python 3.6.1
Traceback (most recent call last):
  File "D:/python/平时代码/test_future.py", line 21, in <module>
    raise ValueError('此处触发一个ValueError') from None
ValueError: 此处触发一个ValueError
"""

 

6.7 其它说明

从python2到python3,代码和性能都得到的优化,有的简化了代码,如:字典方法、函数方法。有的简化了性能,如迭代器,range函数等。

案例1:函数方法

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

def foo(a=3):
    pass

print(dir(foo))

"""
当前版本Python 2.7.14
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
"""

"""
当前版本Python 3.6.1
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
"""

案例2:字典方法

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

d = {'foo':123}

print(dir(d))

"""
当前版本Python 2.7.14
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']
"""

"""
当前版本Python 3.6.1
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
"""

案例3:range函数,在python2中,有range与xrange函数,range产生就是一个list对象,xrange则是生成器对象,在python3中,只有range函数,xrange函数已经取消,同样它也是一个生成器对象。

# -*- coding: utf-8 -*-

# @Time    : 2019/12/6 0:36
# @Author  : hccfm
# @File    : test_future.py
# @Software: PyCharm

from __future__ import print_function
import platform

import six
if six.PY2:
    print('当前版本Python',format(platform.python_version()))
else:
    print("当前版本Python",format(platform.python_version()))

# ran1 = xrange(10)
ran2 = range(10)

# print(type(ran1))
print(type(ran2))

"""
当前版本Python 2.7.14
<type 'xrange'>
<type 'list'>
"""

"""
当前版本Python 3.6.1
<class 'range'>
"""

 

5. 常见函数与版本对应的函数

Python3 Python2 six.moves
Configparser ConfigParser Configparser
filter Itertools.ifilter filter
input raw_input input
range xrange range
functools.reduce reduce reduce
socketserver SocketServer socketserver
map itertools.imap map
zip itertools.izip zip

 

此文章,来源《Python高级编程》,网络博客,官方文档及个人见解而成,如有错误,谢谢留言,不胜感激!!!。

 

END!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章