环境说明 :
Python2.7.11 -> Python3.6
Centos7.5
文档说明 :
本文主要用于
项目 Python2 迁移升级到 Python3
学习了解 Python3
本文主要来源于
知乎-Python23 差异
菜鸟教程-Python23 差异
官网-Python23 差异
主要区别 Python23 主要区别 :
统一了字符编码支持。
增加了新的语法。print/exec 等成为了函数,格式化字符串变量,类型标注,添加了 nonlocal、yield from、async/await、yield for 关键词和annotations 、context 、traceback 、qualname 等 dunder 方法。
修改了一些语法。metaclass,raise、map、filter 以及 dict 的 items/keys/values 方法返回迭代对象而不是列表,描述符协议,保存类属性定义顺序,保存关键字参数顺序
去掉了一些语法。cmp、<>(也就是!=)、xrange(其实就是 range)、不再有经典类
增加一些新的模块。concurrent.futures、venv、unittest.mock、asyncio、selectors、typing 等
修改了一些模块。主要是对模块添加函数/类/方法(如 functools.lru_cache、threading.Barrier)或者参数。
模块改名。把一些相关的模块放进同一个包里面(如 httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib 放进了 http 里面,urllib, urllib2, urlparse, robotparse 放进了 urllib 里面),个例如 SocketServer 改成了 socketserver,Queue 改成 queue 等 8. 去掉了一些模块或者函数。gopherlib、md5、contextlib.nested、inspect.getmoduleinfo 等。
优化。重新实现了 dict 可以减少 20%-25%的内存使用;提升 pickle 序列化和反序列化的效率;collections.OrderedDict 改用 C 实现;通过 os.scandir 对 glob 模块中的 glob()及 iglob()进行优化,使得它们现在大概快了 3-6 倍等.. 这些都是喜大普奔的好消息,同样开发者不需要感知,默默的就会让结果变得更好。
其他。构建过程、C 的 API、安全性等方面的修改,通常对于开发者不需要关心。
核心语法差异 Python23 主要变化项
字符串: 解决了编码问题
编码: 由默认 asscii, 变为 utf-8
返回可迭代对象,而不是列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 如果在 xrange 章节看到的,现在在 Python 3 中一些方法和函数返回迭代对象 -- 代替 Python 2 中的列表 因为我们通常那些遍历只有一次,我认为这个改变对节约内存很有意义。尽管如此,它也是可能的,相对于生成器 --- 如需要遍历多次。它是不那么高效的。 而对于那些情况下,我们真正需要的是列表对象,我们可以通过 list () 函数简单的把迭代对象转换成一个列表。 print range (3 )print type (range (3 ))[0 , 1 , 2 ] <type 'list' > print (range (3 ))print (type (range (3 )))print (list (range (3 )))range (0 , 3 )<class 'range '> [0, 1, 2]
在 Python 3 中一些经常使用到的不再返回列表的函数和方法:
zip()
map()
filter()
dictionary’s .keys() method
dictionary’s .values() method
dictionary’s .items() method
字符串 & 编码 字符串是最大的变化之一,
在 Python2 中,字符串有两个类型,一个是 unicode,一个是 str,前者表示文本字符串,后者表示字节序列
在 Python3 中两者做了严格区分,分别用 str 表示字符串,byte 表示字节序列,任何需要写入文本或者网络传输的数据都只接收字节序列
Python2 的默认编码是 asscii
Python3 默认采用了 UTF-8 作为默认编码,因此你不再需要在文件顶部写 # coding=utf-8
1 2 3 4 5 6 7 >>> sys.getdefaultencoding()'ascii' >>> sys.getdefaultencoding()'utf-8'
格式化字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 在Python中格式化语法的方式大家通常都会偏向于【Format】或者 【%S】这两种方法,操作如下: print ("My name is %s" % ('phithon' , ))print ("My name is %(name)s" % {'name' :'phithon' })print ("My name is {}" .format ("bob" ))print ("My name is {name}" .format (name="bob" ))而到了Python3.6 版本,推出了新的格式化字符串的灵活方法【f-string】, 使用【f-string】编写的与上面功能相同的代码是这样的 name="bob" print (f"My name is {name} " )我们对比这几种格式化字符串的方法,可以发现相比于常见的字符串格式符【%S】 或 【Format】 方法, 【f-string】 直接在占位符中插入变量显得更加方便,也更好理解,
路径管理库 Pathlib(最低 Python 版本为 3.4) 枚举(最低 Python 版本为 3.4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from enum import Enum, autoclass Monster (Enum ): ZOMBIE = auto() WARRIOR = auto() BEAR = auto() print (Monster.ZOMBIE)for i in Monster: print (i)
原生 LRU 缓存(最低 Python 版本为 3.2) TODO LRU 缓存 缓存是大家在开发中都会用到的一个特性,如果我们准确的使用好它,它会节省我们很多时间和成本。相信很多人初学 Python 装饰器的时候都会去实现一个缓存的装饰器来节省斐波那契函数的计算时间。而 Python 3 之后将 LRU(最近最少使用算法)缓存作为一个名为「lru_cache」的装饰器,使得对缓存的使用非常简单。
1 2 3 4 5 6 7 8 9 10 11 12 from functools import lru_cache@lru_cache(maxsize=512 ) def fib_memoization (number: int ) -> int : if number == 0 : return 0 if number == 1 : return 1 return fib_memoization(number-1 ) + fib_memoization(number-2 ) start = time.time() fib_memoization(40 ) print (f'Duration: {time.time() - start} s' )
扩展的可迭代对象解包(最低 Python 版本为 3.0) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Python解包相信在我们初学Python的时候都有所了解,如果我们很多地掌握这个特性,相信是一件非常酷的事情。那什么是扩展的解包呢?我们可以从pep3132中了解更多,举个例子: >>> print (*[1 ,2 ,3 ], *[3 ,4 ]) File "<stdin>" , line 1 print (*[1 ,2 ,3 ], *[3 ,4 ]) ^ SyntaxError: invalid syntax >>> >>> print (*[1 ], *[2 ], 3 )1 2 3 >>> *range (4 ), 4 (0 , 1 , 2 , 3 , 4 ) >>> [*range (4 ), 4 ][0 , 1 , 2 , 3 , 4 ] >>> {*range (4 ), 4 }{0 , 1 , 2 , 3 , 4 } >>> {'x' : 1 , **{'y' : 2 }}{'x' : 1 , 'y' : 2 }我们可以看到,解包这个操作也算的上Python中极其潮流的玩法了,耍的一手好解包,真的会秀翻全场啊!
Data class 装饰器(最低 Python 版本为 3.7) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Python 3.7 引入了【data class 】,新特性大大简化了定义类对象的代码量,代码简洁明晰。通过使用@dataclass 装饰器来修饰类的设计,可以用来减少对样板代码的使用,因为装饰器会自动生成诸如「__init__ ()」和「__repr ()__ 」这样的特殊方法。在官方的文档中,它们被描述为「带有缺省值的可变命名元组」。from dataclasses import dataclass @dataclass class DataClassCard : rank: str suit: str queen_of_hearts = DataClassCard('Q' , 'Hearts' ) print (queen_of_hearts.rank)print (queen_of_hearts)print (queen_of_hearts == DataClassCard('Q' , 'Hearts' ))
类型提示 Type hinting 1 2 3 4 3. 类型提示 Type hinting(最低 Python 版本为 3.5 )编程语言有很多类型,静态编译型语言和动态解释型语言的对比是软件工程中一个热门的话题,几乎每个人对此有自己的看法。在静态语言中类型标注无疑是让人又爱又恨,爱的是编译速度加快,团队合作中准确了解函数方法的入参类型,恨的是Coding时极其繁琐的标注。不过,标注这种极其符合团队文化的操作还是在Python3中被引入,并且很快得到了人们的喜爱。def print_yes_or_no (codition: str ) -> bool : pass
细节语法差异 next() and .next() 1 2 3 4 5 next () 和 .next () 都可以使用只能使用 next ()
nonlocal Python3 中新增 非局部变量 nonlocal,用于设置嵌套函数
unicode,字符串 u’’ 1 2 3 4 5 6 7 u"根据orm模型重建表" "根据orm模型重建表" 字符串、注释、unicode(xxx) 都需要去掉 u"" ,因为Python3默认为unicode,无需u前缀标识 unicode Python3加u'' 不会报错,但是无实际含义
字典的 items 加 list 1 2 3 4 5 6 7 8 9 10 11 12 savepath_dict.items() list (savepath_dict.items())>>> a = {'a' :123 }>>> a.items()dict_items([('a' , 123 )]) >>> list (a.items())[('a' , 123 )] 字典的items加list Python3不加list 也不会报错
print 语法 1 2 3 4 5 6 7 8 print "请输入正确的时间格式: yyyy-mm-dd" print ("请输入正确的时间格式: yyyy-mm-dd" )1. Python2中print 作为语句,Python3中print 作为函数使用(接收字符串作为参数)
除法运算 除法运算 Python3 保留小数部分
1 2 3 4 5 6 7 8 9 10 In [11 ]: 1 /2 Out[11 ]: 0 In [12 ]: 1 /2 Out[12 ]: 0.5 In [13 ]: 1 //2 Out[13 ]: 0
xrange 在 Python3 中被去除 八进制字面量表示 Python3 中八进制不允许简写
1 2 3 4 5 6 7 8 9 >>> 0o1000 512 >>> 01000512 >>> 0o1000 512
模块名称修改 Python3 中模块包名称符合 pep8 规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 _winreg ConfigParser copy_reg Queue SocketServer repr winreg configparser copyreg queue socketserver reprlib
数据类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 )Py3.X去除了long类型,现在只有一种整型——int ,但它的行为就像2. X版本的long2 )新增了bytes 类型,对应于2. X版本的八位串,定义一个bytes 字面量的方法如下:>>> b = b'china' >>> type (b)<type 'bytes' > str 对象和 bytes 对象可以使用 .encode() (str -> bytes ) 或 .decode() (bytes -> str )方法相互转化。>>> s = b.decode()>>> s'china' >>> b1 = s.encode()>>> b1b'china' 3 )dict 的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函数都被废弃。同时去掉的还有 dict .has_key(),用 in 替代它吧
从键盘录入一个字符串 1 2 3 4 5 raw_input("提示信息" ) input ("提示信息" )
不等运算符 Python 2.x 中不等于有两种写法 != 和 <>
Python 3.x 中去掉了<>, 只有!=一种写法,还好,我从来没有使用<>的习惯
隐式命名空间包(最低 Python 版本为 3.3) 在 Python 2 中,上面每个文件夹都必须包含将文件夹转化为 Python 程序包的__init__.py
文件。
在 Python 3 中,随着隐式命名空间包的引入,这些文件不再是必须的了。
但建议有__init__.py
文件
True and False
basestring 1 2 3 4 5 isinstance (fields, basestring)isinstance (fields, str )
has_key 1 2 3 4 5 6 7 8 if not rst.has_key("aggregations" ):if "aggregations" not in rst:Python3中可以使用 key not in dic 来识别key是否在字典中, Python3中没有 dic.has_key('xxxx' )
sys reload 语法 1 2 3 4 5 6 7 import sysreload(sys) sys.setdefaultencoding('utf8' ) import sys
to_md5(x) 1 2 3 4 5 6 7 8 9 addr_df["peer_node_id" ] = addr_df["peer_node_label" ]. \ apply(lambda x: to_md5(x)) to_md5(x.encode('utf-8' )) 否则报错 TypeError: Unicode-objects must be encoded before hashing
min/max 函数 1 2 3 4 5 6 7 8 9 10 Min/max 函数在 Python 3 中,如果想对列表排序或找到最大/最小值,所有的元素必须可以比较。如果你原来的代码是 Python 2 写的,里面有包含 None 元素的列表,那么换到 Python 3 时就可能会出现一些问题。那么可以用 min /max 函数来解决这种冲突。def listmin (L ): ''' Returns min of an iterable L, Ignoring null (None) values. If all values are null, returns None ''' values = [v for v in L if v is not None ] return min (values) if values else None 也可以写一个相似的函数来确定最大元素。
cmp 1 2 3 4 5 6 7 8 9 10 11 cmp(1 ,2 ) python3移除了cmp()函数,但提供了六个丰富的比较运算符,详见此处 import operator operator.gt(1 ,2 ) operator.ge(1 ,2 ) operator.eq(1 ,2 ) operator.le(1 ,2 ) operator.lt(1 ,2 )
except 语法 1 2 3 4 5 6 7 8 except Exception, err: print (err.message) except Exception as err: print (str (err))
虚拟变量,For 循环变量和全局命名空间泄漏 1 2 3 4 5 6 7 8 9 在使用由不同版本 Python 编写的代码时,还有一个很有意思的地方。 from __future__ import print_functiona = [i for i in range (10 )] print (i)如果我们在 Python 2 解释器上运行这段代码,我们会得到结果 9 ,因为用于列表推导式的 i 变量留在了内存中。如果你在下部分代码中忘了这回事,再使用 i 变量的话,会导致不可见的错误。 在 Python 3 中一切更为简单,在这个例子中的变量只在列表的创建期间使用,之后不再保存。这样当我们运行代码时,就会看到如下结果: NameError: name 'i' is not defined
func.func_name 1 2 3 4 5 func.func_name func.__name__
软件差异 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ModuleNotFoundError: No module named '_bz2' Pandas==0.25 .3 报此错误 更改安装 pandas==0.24 .2 import unioutpython3 中没有 uniout python2 gunicorn -c fdm/base/gun.conf fdm.views:app python3 配置文件必须有 .py 扩展名 gunicorn -c fdm/base/gun.conf.py fdm.views:app 否则报错 !!! !!! WARNING: configuration file should have a valid Python extension. !!! python2 workers = multiprocessing.cpu_count() / 4 + 1 python3 workers 只接受 int 参数 workers = int (multiprocessing.cpu_count() / 4 + 1 )
from module import *
只能用于模块,不能用于函数from .[module] import name
from .[module] import name
是相对导入的唯一正确语法,所有不以.开头的导入都被当成绝对导入
参考链接
title: Python23差异对比02 url_path: python/advance/Python23差异对比02 tags:
python
python-进阶 categories:
python
python-进阶 description: Python23差异对比02
tags: Python2 Python3 差异对比 基础知识 2020 年 01 月
Python2.7.11&Python3.6.0 差异 环境说明 :
Python2.7.11 -> Python3.6
Centos7.5
文档说明 :
本文主要用于
项目 Python2 迁移升级到 Python3
学习了解 Python3
本文主要来源于
知乎-Python23 差异
菜鸟教程-Python23 差异
官网-Python23 差异
主要区别 Python23 主要区别 :
统一了字符编码支持。
增加了新的语法。print/exec 等成为了函数,格式化字符串变量,类型标注,添加了 nonlocal、yield from、async/await、yield for 关键词和annotations 、context 、traceback 、qualname 等 dunder 方法。
修改了一些语法。metaclass,raise、map、filter 以及 dict 的 items/keys/values 方法返回迭代对象而不是列表,描述符协议,保存类属性定义顺序,保存关键字参数顺序
去掉了一些语法。cmp、<>(也就是!=)、xrange(其实就是 range)、不再有经典类
增加一些新的模块。concurrent.futures、venv、unittest.mock、asyncio、selectors、typing 等
修改了一些模块。主要是对模块添加函数/类/方法(如 functools.lru_cache、threading.Barrier)或者参数。
模块改名。把一些相关的模块放进同一个包里面(如 httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib 放进了 http 里面,urllib, urllib2, urlparse, robotparse 放进了 urllib 里面),个例如 SocketServer 改成了 socketserver,Queue 改成 queue 等 8. 去掉了一些模块或者函数。gopherlib、md5、contextlib.nested、inspect.getmoduleinfo 等。
优化。重新实现了 dict 可以减少 20%-25%的内存使用;提升 pickle 序列化和反序列化的效率;collections.OrderedDict 改用 C 实现;通过 os.scandir 对 glob 模块中的 glob()及 iglob()进行优化,使得它们现在大概快了 3-6 倍等.. 这些都是喜大普奔的好消息,同样开发者不需要感知,默默的就会让结果变得更好。
其他。构建过程、C 的 API、安全性等方面的修改,通常对于开发者不需要关心。
核心语法差异 Python23 主要变化项
字符串: 解决了编码问题
编码: 由默认 asscii, 变为 utf-8
返回可迭代对象,而不是列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 如果在 xrange 章节看到的,现在在 Python 3 中一些方法和函数返回迭代对象 -- 代替 Python 2 中的列表 因为我们通常那些遍历只有一次,我认为这个改变对节约内存很有意义。尽管如此,它也是可能的,相对于生成器 --- 如需要遍历多次。它是不那么高效的。 而对于那些情况下,我们真正需要的是列表对象,我们可以通过 list () 函数简单的把迭代对象转换成一个列表。 print range (3 )print type (range (3 ))[0 , 1 , 2 ] <type 'list' > print (range (3 ))print (type (range (3 )))print (list (range (3 )))range (0 , 3 )<class 'range '> [0, 1, 2]
在 Python 3 中一些经常使用到的不再返回列表的函数和方法:
zip()
map()
filter()
dictionary’s .keys() method
dictionary’s .values() method
dictionary’s .items() method
字符串 & 编码 字符串是最大的变化之一,
在 Python2 中,字符串有两个类型,一个是 unicode,一个是 str,前者表示文本字符串,后者表示字节序列
在 Python3 中两者做了严格区分,分别用 str 表示字符串,byte 表示字节序列,任何需要写入文本或者网络传输的数据都只接收字节序列
Python2 的默认编码是 asscii
Python3 默认采用了 UTF-8 作为默认编码,因此你不再需要在文件顶部写 # coding=utf-8
1 2 3 4 5 6 7 >>> sys.getdefaultencoding()'ascii' >>> sys.getdefaultencoding()'utf-8'
格式化字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 在Python中格式化语法的方式大家通常都会偏向于【Format】或者 【%S】这两种方法,操作如下: print ("My name is %s" % ('phithon' , ))print ("My name is %(name)s" % {'name' :'phithon' })print ("My name is {}" .format ("bob" ))print ("My name is {name}" .format (name="bob" ))而到了Python3.6 版本,推出了新的格式化字符串的灵活方法【f-string】, 使用【f-string】编写的与上面功能相同的代码是这样的 name="bob" print (f"My name is {name} " )我们对比这几种格式化字符串的方法,可以发现相比于常见的字符串格式符【%S】 或 【Format】 方法, 【f-string】 直接在占位符中插入变量显得更加方便,也更好理解,
路径管理库 Pathlib(最低 Python 版本为 3.4) 枚举(最低 Python 版本为 3.4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from enum import Enum, autoclass Monster (Enum ): ZOMBIE = auto() WARRIOR = auto() BEAR = auto() print (Monster.ZOMBIE)for i in Monster: print (i)
原生 LRU 缓存(最低 Python 版本为 3.2) TODO LRU 缓存 缓存是大家在开发中都会用到的一个特性,如果我们准确的使用好它,它会节省我们很多时间和成本。相信很多人初学 Python 装饰器的时候都会去实现一个缓存的装饰器来节省斐波那契函数的计算时间。而 Python 3 之后将 LRU(最近最少使用算法)缓存作为一个名为「lru_cache」的装饰器,使得对缓存的使用非常简单。
1 2 3 4 5 6 7 8 9 10 11 12 from functools import lru_cache@lru_cache(maxsize=512 ) def fib_memoization (number: int ) -> int : if number == 0 : return 0 if number == 1 : return 1 return fib_memoization(number-1 ) + fib_memoization(number-2 ) start = time.time() fib_memoization(40 ) print (f'Duration: {time.time() - start} s' )
扩展的可迭代对象解包(最低 Python 版本为 3.0) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Python解包相信在我们初学Python的时候都有所了解,如果我们很多地掌握这个特性,相信是一件非常酷的事情。那什么是扩展的解包呢?我们可以从pep3132中了解更多,举个例子: >>> print (*[1 ,2 ,3 ], *[3 ,4 ]) File "<stdin>" , line 1 print (*[1 ,2 ,3 ], *[3 ,4 ]) ^ SyntaxError: invalid syntax >>> >>> print (*[1 ], *[2 ], 3 )1 2 3 >>> *range (4 ), 4 (0 , 1 , 2 , 3 , 4 ) >>> [*range (4 ), 4 ][0 , 1 , 2 , 3 , 4 ] >>> {*range (4 ), 4 }{0 , 1 , 2 , 3 , 4 } >>> {'x' : 1 , **{'y' : 2 }}{'x' : 1 , 'y' : 2 }我们可以看到,解包这个操作也算的上Python中极其潮流的玩法了,耍的一手好解包,真的会秀翻全场啊!
Data class 装饰器(最低 Python 版本为 3.7) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Python 3.7 引入了【data class 】,新特性大大简化了定义类对象的代码量,代码简洁明晰。通过使用@dataclass 装饰器来修饰类的设计,可以用来减少对样板代码的使用,因为装饰器会自动生成诸如「__init__ ()」和「__repr ()__ 」这样的特殊方法。在官方的文档中,它们被描述为「带有缺省值的可变命名元组」。from dataclasses import dataclass @dataclass class DataClassCard : rank: str suit: str queen_of_hearts = DataClassCard('Q' , 'Hearts' ) print (queen_of_hearts.rank)print (queen_of_hearts)print (queen_of_hearts == DataClassCard('Q' , 'Hearts' ))
类型提示 Type hinting 1 2 3 4 3. 类型提示 Type hinting(最低 Python 版本为 3.5 )编程语言有很多类型,静态编译型语言和动态解释型语言的对比是软件工程中一个热门的话题,几乎每个人对此有自己的看法。在静态语言中类型标注无疑是让人又爱又恨,爱的是编译速度加快,团队合作中准确了解函数方法的入参类型,恨的是Coding时极其繁琐的标注。不过,标注这种极其符合团队文化的操作还是在Python3中被引入,并且很快得到了人们的喜爱。def print_yes_or_no (codition: str ) -> bool : pass
细节语法差异 next() and .next() 1 2 3 4 5 next () 和 .next () 都可以使用只能使用 next ()
nonlocal Python3 中新增 非局部变量 nonlocal,用于设置嵌套函数
unicode,字符串 u’’ 1 2 3 4 5 6 7 u"根据orm模型重建表" "根据orm模型重建表" 字符串、注释、unicode(xxx) 都需要去掉 u"" ,因为Python3默认为unicode,无需u前缀标识 unicode Python3加u'' 不会报错,但是无实际含义
字典的 items 加 list 1 2 3 4 5 6 7 8 9 10 11 12 savepath_dict.items() list (savepath_dict.items())>>> a = {'a' :123 }>>> a.items()dict_items([('a' , 123 )]) >>> list (a.items())[('a' , 123 )] 字典的items加list Python3不加list 也不会报错
print 语法 1 2 3 4 5 6 7 8 print "请输入正确的时间格式: yyyy-mm-dd" print ("请输入正确的时间格式: yyyy-mm-dd" )1. Python2中print 作为语句,Python3中print 作为函数使用(接收字符串作为参数)
除法运算 除法运算 Python3 保留小数部分
1 2 3 4 5 6 7 8 9 10 In [11 ]: 1 /2 Out[11 ]: 0 In [12 ]: 1 /2 Out[12 ]: 0.5 In [13 ]: 1 //2 Out[13 ]: 0
xrange 在 Python3 中被去除 八进制字面量表示 Python3 中八进制不允许简写
1 2 3 4 5 6 7 8 9 >>> 0o1000 512 >>> 01000512 >>> 0o1000 512
模块名称修改 Python3 中模块包名称符合 pep8 规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 _winreg ConfigParser copy_reg Queue SocketServer repr winreg configparser copyreg queue socketserver reprlib
数据类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 )Py3.X去除了long类型,现在只有一种整型——int ,但它的行为就像2. X版本的long2 )新增了bytes 类型,对应于2. X版本的八位串,定义一个bytes 字面量的方法如下:>>> b = b'china' >>> type (b)<type 'bytes' > str 对象和 bytes 对象可以使用 .encode() (str -> bytes ) 或 .decode() (bytes -> str )方法相互转化。>>> s = b.decode()>>> s'china' >>> b1 = s.encode()>>> b1b'china' 3 )dict 的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函数都被废弃。同时去掉的还有 dict .has_key(),用 in 替代它吧
从键盘录入一个字符串 1 2 3 4 5 raw_input("提示信息" ) input ("提示信息" )
不等运算符 Python 2.x 中不等于有两种写法 != 和 <>
Python 3.x 中去掉了<>, 只有!=一种写法,还好,我从来没有使用<>的习惯
隐式命名空间包(最低 Python 版本为 3.3) 在 Python 2 中,上面每个文件夹都必须包含将文件夹转化为 Python 程序包的__init__.py
文件。
在 Python 3 中,随着隐式命名空间包的引入,这些文件不再是必须的了。
但建议有__init__.py
文件
True and False
basestring 1 2 3 4 5 isinstance (fields, basestring)isinstance (fields, str )
has_key 1 2 3 4 5 6 7 8 if not rst.has_key("aggregations" ):if "aggregations" not in rst:Python3中可以使用 key not in dic 来识别key是否在字典中, Python3中没有 dic.has_key('xxxx' )
sys reload 语法 1 2 3 4 5 6 7 import sysreload(sys) sys.setdefaultencoding('utf8' ) import sys
to_md5(x) 1 2 3 4 5 6 7 8 9 addr_df["peer_node_id" ] = addr_df["peer_node_label" ]. \ apply(lambda x: to_md5(x)) to_md5(x.encode('utf-8' )) 否则报错 TypeError: Unicode-objects must be encoded before hashing
min/max 函数 1 2 3 4 5 6 7 8 9 10 Min/max 函数在 Python 3 中,如果想对列表排序或找到最大/最小值,所有的元素必须可以比较。如果你原来的代码是 Python 2 写的,里面有包含 None 元素的列表,那么换到 Python 3 时就可能会出现一些问题。那么可以用 min /max 函数来解决这种冲突。def listmin (L ): ''' Returns min of an iterable L, Ignoring null (None) values. If all values are null, returns None ''' values = [v for v in L if v is not None ] return min (values) if values else None 也可以写一个相似的函数来确定最大元素。
cmp 1 2 3 4 5 6 7 8 9 10 11 cmp(1 ,2 ) python3移除了cmp()函数,但提供了六个丰富的比较运算符,详见此处 import operator operator.gt(1 ,2 ) operator.ge(1 ,2 ) operator.eq(1 ,2 ) operator.le(1 ,2 ) operator.lt(1 ,2 )
except 语法 1 2 3 4 5 6 7 8 except Exception, err: print (err.message) except Exception as err: print (str (err))
虚拟变量,For 循环变量和全局命名空间泄漏 1 2 3 4 5 6 7 8 9 在使用由不同版本 Python 编写的代码时,还有一个很有意思的地方。 from __future__ import print_functiona = [i for i in range (10 )] print (i)如果我们在 Python 2 解释器上运行这段代码,我们会得到结果 9 ,因为用于列表推导式的 i 变量留在了内存中。如果你在下部分代码中忘了这回事,再使用 i 变量的话,会导致不可见的错误。 在 Python 3 中一切更为简单,在这个例子中的变量只在列表的创建期间使用,之后不再保存。这样当我们运行代码时,就会看到如下结果: NameError: name 'i' is not defined
func.func_name 1 2 3 4 5 func.func_name func.__name__
软件差异 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ModuleNotFoundError: No module named '_bz2' Pandas==0.25 .3 报此错误 更改安装 pandas==0.24 .2 import unioutpython3 中没有 uniout python2 gunicorn -c fdm/base/gun.conf fdm.views:app python3 配置文件必须有 .py 扩展名 gunicorn -c fdm/base/gun.conf.py fdm.views:app 否则报错 !!! !!! WARNING: configuration file should have a valid Python extension. !!! python2 workers = multiprocessing.cpu_count() / 4 + 1 python3 workers 只接受 int 参数 workers = int (multiprocessing.cpu_count() / 4 + 1 )
from module import *
只能用于模块,不能用于函数from .[module] import name
from .[module] import name
是相对导入的唯一正确语法,所有不以.开头的导入都被当成绝对导入
Python2.7 升级到 Python3.6 Python3 自带 2to3 工具: 2to3 -w
文件/文件夹路径
项目代码修改:
2to3
去除 unicode
print
except,err
has_key
list(child_menus.get(menu_id, {}).items()) 字典加 list
raw_input
<>
basestring
hashlib.md5(dataset_name.encode(‘utf-8’) 增加 encode
sys reload 手动去除
cmp
待修改项:
除法运算。 所有 /
项都需要检查
参考链接
title: Python23差异对比02 url_path: python/advance/Python23差异对比02 tags:
python
python-进阶 categories:
python
python-进阶 description: Python23差异对比02
tags: Python2 Python3 差异对比 基础知识 2020 年 01 月
Python2.7.11&Python3.6.0 差异 环境说明 :
Python2.7.11 -> Python3.6
Centos7.5
文档说明 :
本文主要用于
项目 Python2 迁移升级到 Python3
学习了解 Python3
本文主要来源于
知乎-Python23 差异
菜鸟教程-Python23 差异
官网-Python23 差异
主要区别 Python23 主要区别 :
统一了字符编码支持。
增加了新的语法。print/exec 等成为了函数,格式化字符串变量,类型标注,添加了 nonlocal、yield from、async/await、yield for 关键词和annotations 、context 、traceback 、qualname 等 dunder 方法。
修改了一些语法。metaclass,raise、map、filter 以及 dict 的 items/keys/values 方法返回迭代对象而不是列表,描述符协议,保存类属性定义顺序,保存关键字参数顺序
去掉了一些语法。cmp、<>(也就是!=)、xrange(其实就是 range)、不再有经典类
增加一些新的模块。concurrent.futures、venv、unittest.mock、asyncio、selectors、typing 等
修改了一些模块。主要是对模块添加函数/类/方法(如 functools.lru_cache、threading.Barrier)或者参数。
模块改名。把一些相关的模块放进同一个包里面(如 httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib 放进了 http 里面,urllib, urllib2, urlparse, robotparse 放进了 urllib 里面),个例如 SocketServer 改成了 socketserver,Queue 改成 queue 等 8. 去掉了一些模块或者函数。gopherlib、md5、contextlib.nested、inspect.getmoduleinfo 等。
优化。重新实现了 dict 可以减少 20%-25%的内存使用;提升 pickle 序列化和反序列化的效率;collections.OrderedDict 改用 C 实现;通过 os.scandir 对 glob 模块中的 glob()及 iglob()进行优化,使得它们现在大概快了 3-6 倍等.. 这些都是喜大普奔的好消息,同样开发者不需要感知,默默的就会让结果变得更好。
其他。构建过程、C 的 API、安全性等方面的修改,通常对于开发者不需要关心。
核心语法差异 Python23 主要变化项
字符串: 解决了编码问题
编码: 由默认 asscii, 变为 utf-8
返回可迭代对象,而不是列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 如果在 xrange 章节看到的,现在在 Python 3 中一些方法和函数返回迭代对象 -- 代替 Python 2 中的列表 因为我们通常那些遍历只有一次,我认为这个改变对节约内存很有意义。尽管如此,它也是可能的,相对于生成器 --- 如需要遍历多次。它是不那么高效的。 而对于那些情况下,我们真正需要的是列表对象,我们可以通过 list () 函数简单的把迭代对象转换成一个列表。 print range (3 )print type (range (3 ))[0 , 1 , 2 ] <type 'list' > print (range (3 ))print (type (range (3 )))print (list (range (3 )))range (0 , 3 )<class 'range '> [0, 1, 2]
在 Python 3 中一些经常使用到的不再返回列表的函数和方法:
zip()
map()
filter()
dictionary’s .keys() method
dictionary’s .values() method
dictionary’s .items() method
字符串 & 编码 字符串是最大的变化之一,
在 Python2 中,字符串有两个类型,一个是 unicode,一个是 str,前者表示文本字符串,后者表示字节序列
在 Python3 中两者做了严格区分,分别用 str 表示字符串,byte 表示字节序列,任何需要写入文本或者网络传输的数据都只接收字节序列
Python2 的默认编码是 asscii
Python3 默认采用了 UTF-8 作为默认编码,因此你不再需要在文件顶部写 # coding=utf-8
1 2 3 4 5 6 7 >>> sys.getdefaultencoding()'ascii' >>> sys.getdefaultencoding()'utf-8'
格式化字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 在Python中格式化语法的方式大家通常都会偏向于【Format】或者 【%S】这两种方法,操作如下: print ("My name is %s" % ('phithon' , ))print ("My name is %(name)s" % {'name' :'phithon' })print ("My name is {}" .format ("bob" ))print ("My name is {name}" .format (name="bob" ))而到了Python3.6 版本,推出了新的格式化字符串的灵活方法【f-string】, 使用【f-string】编写的与上面功能相同的代码是这样的 name="bob" print (f"My name is {name} " )我们对比这几种格式化字符串的方法,可以发现相比于常见的字符串格式符【%S】 或 【Format】 方法, 【f-string】 直接在占位符中插入变量显得更加方便,也更好理解,
路径管理库 Pathlib(最低 Python 版本为 3.4) 枚举(最低 Python 版本为 3.4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from enum import Enum, autoclass Monster (Enum ): ZOMBIE = auto() WARRIOR = auto() BEAR = auto() print (Monster.ZOMBIE)for i in Monster: print (i)
原生 LRU 缓存(最低 Python 版本为 3.2) TODO LRU 缓存 缓存是大家在开发中都会用到的一个特性,如果我们准确的使用好它,它会节省我们很多时间和成本。相信很多人初学 Python 装饰器的时候都会去实现一个缓存的装饰器来节省斐波那契函数的计算时间。而 Python 3 之后将 LRU(最近最少使用算法)缓存作为一个名为「lru_cache」的装饰器,使得对缓存的使用非常简单。
1 2 3 4 5 6 7 8 9 10 11 12 from functools import lru_cache@lru_cache(maxsize=512 ) def fib_memoization (number: int ) -> int : if number == 0 : return 0 if number == 1 : return 1 return fib_memoization(number-1 ) + fib_memoization(number-2 ) start = time.time() fib_memoization(40 ) print (f'Duration: {time.time() - start} s' )
扩展的可迭代对象解包(最低 Python 版本为 3.0) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Python解包相信在我们初学Python的时候都有所了解,如果我们很多地掌握这个特性,相信是一件非常酷的事情。那什么是扩展的解包呢?我们可以从pep3132中了解更多,举个例子: >>> print (*[1 ,2 ,3 ], *[3 ,4 ]) File "<stdin>" , line 1 print (*[1 ,2 ,3 ], *[3 ,4 ]) ^ SyntaxError: invalid syntax >>> >>> print (*[1 ], *[2 ], 3 )1 2 3 >>> *range (4 ), 4 (0 , 1 , 2 , 3 , 4 ) >>> [*range (4 ), 4 ][0 , 1 , 2 , 3 , 4 ] >>> {*range (4 ), 4 }{0 , 1 , 2 , 3 , 4 } >>> {'x' : 1 , **{'y' : 2 }}{'x' : 1 , 'y' : 2 }我们可以看到,解包这个操作也算的上Python中极其潮流的玩法了,耍的一手好解包,真的会秀翻全场啊!
Data class 装饰器(最低 Python 版本为 3.7) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Python 3.7 引入了【data class 】,新特性大大简化了定义类对象的代码量,代码简洁明晰。通过使用@dataclass 装饰器来修饰类的设计,可以用来减少对样板代码的使用,因为装饰器会自动生成诸如「__init__ ()」和「__repr ()__ 」这样的特殊方法。在官方的文档中,它们被描述为「带有缺省值的可变命名元组」。from dataclasses import dataclass @dataclass class DataClassCard : rank: str suit: str queen_of_hearts = DataClassCard('Q' , 'Hearts' ) print (queen_of_hearts.rank)print (queen_of_hearts)print (queen_of_hearts == DataClassCard('Q' , 'Hearts' ))
类型提示 Type hinting 1 2 3 4 3. 类型提示 Type hinting(最低 Python 版本为 3.5 )编程语言有很多类型,静态编译型语言和动态解释型语言的对比是软件工程中一个热门的话题,几乎每个人对此有自己的看法。在静态语言中类型标注无疑是让人又爱又恨,爱的是编译速度加快,团队合作中准确了解函数方法的入参类型,恨的是Coding时极其繁琐的标注。不过,标注这种极其符合团队文化的操作还是在Python3中被引入,并且很快得到了人们的喜爱。def print_yes_or_no (codition: str ) -> bool : pass
细节语法差异 next() and .next() 1 2 3 4 5 next () 和 .next () 都可以使用只能使用 next ()
nonlocal Python3 中新增 非局部变量 nonlocal,用于设置嵌套函数
unicode,字符串 u’’ 1 2 3 4 5 6 7 u"根据orm模型重建表" "根据orm模型重建表" 字符串、注释、unicode(xxx) 都需要去掉 u"" ,因为Python3默认为unicode,无需u前缀标识 unicode Python3加u'' 不会报错,但是无实际含义
字典的 items 加 list 1 2 3 4 5 6 7 8 9 10 11 12 savepath_dict.items() list (savepath_dict.items())>>> a = {'a' :123 }>>> a.items()dict_items([('a' , 123 )]) >>> list (a.items())[('a' , 123 )] 字典的items加list Python3不加list 也不会报错
print 语法 1 2 3 4 5 6 7 8 print "请输入正确的时间格式: yyyy-mm-dd" print ("请输入正确的时间格式: yyyy-mm-dd" )1. Python2中print 作为语句,Python3中print 作为函数使用(接收字符串作为参数)
除法运算 除法运算 Python3 保留小数部分
1 2 3 4 5 6 7 8 9 10 In [11 ]: 1 /2 Out[11 ]: 0 In [12 ]: 1 /2 Out[12 ]: 0.5 In [13 ]: 1 //2 Out[13 ]: 0
xrange 在 Python3 中被去除 八进制字面量表示 Python3 中八进制不允许简写
1 2 3 4 5 6 7 8 9 >>> 0o1000 512 >>> 01000512 >>> 0o1000 512
模块名称修改 Python3 中模块包名称符合 pep8 规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 _winreg ConfigParser copy_reg Queue SocketServer repr winreg configparser copyreg queue socketserver reprlib
数据类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 )Py3.X去除了long类型,现在只有一种整型——int ,但它的行为就像2. X版本的long2 )新增了bytes 类型,对应于2. X版本的八位串,定义一个bytes 字面量的方法如下:>>> b = b'china' >>> type (b)<type 'bytes' > str 对象和 bytes 对象可以使用 .encode() (str -> bytes ) 或 .decode() (bytes -> str )方法相互转化。>>> s = b.decode()>>> s'china' >>> b1 = s.encode()>>> b1b'china' 3 )dict 的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函数都被废弃。同时去掉的还有 dict .has_key(),用 in 替代它吧
从键盘录入一个字符串 1 2 3 4 5 raw_input("提示信息" ) input ("提示信息" )
不等运算符 Python 2.x 中不等于有两种写法 != 和 <>
Python 3.x 中去掉了<>, 只有!=一种写法,还好,我从来没有使用<>的习惯
隐式命名空间包(最低 Python 版本为 3.3) 在 Python 2 中,上面每个文件夹都必须包含将文件夹转化为 Python 程序包的__init__.py
文件。
在 Python 3 中,随着隐式命名空间包的引入,这些文件不再是必须的了。
但建议有__init__.py
文件
True and False
basestring 1 2 3 4 5 isinstance (fields, basestring)isinstance (fields, str )
has_key 1 2 3 4 5 6 7 8 if not rst.has_key("aggregations" ):if "aggregations" not in rst:Python3中可以使用 key not in dic 来识别key是否在字典中, Python3中没有 dic.has_key('xxxx' )
sys reload 语法 1 2 3 4 5 6 7 import sysreload(sys) sys.setdefaultencoding('utf8' ) import sys
to_md5(x) 1 2 3 4 5 6 7 8 9 addr_df["peer_node_id" ] = addr_df["peer_node_label" ]. \ apply(lambda x: to_md5(x)) to_md5(x.encode('utf-8' )) 否则报错 TypeError: Unicode-objects must be encoded before hashing
min/max 函数 1 2 3 4 5 6 7 8 9 10 Min/max 函数在 Python 3 中,如果想对列表排序或找到最大/最小值,所有的元素必须可以比较。如果你原来的代码是 Python 2 写的,里面有包含 None 元素的列表,那么换到 Python 3 时就可能会出现一些问题。那么可以用 min /max 函数来解决这种冲突。def listmin (L ): ''' Returns min of an iterable L, Ignoring null (None) values. If all values are null, returns None ''' values = [v for v in L if v is not None ] return min (values) if values else None 也可以写一个相似的函数来确定最大元素。
cmp 1 2 3 4 5 6 7 8 9 10 11 cmp(1 ,2 ) python3移除了cmp()函数,但提供了六个丰富的比较运算符,详见此处 import operator operator.gt(1 ,2 ) operator.ge(1 ,2 ) operator.eq(1 ,2 ) operator.le(1 ,2 ) operator.lt(1 ,2 )
except 语法 1 2 3 4 5 6 7 8 except Exception, err: print (err.message) except Exception as err: print (str (err))
虚拟变量,For 循环变量和全局命名空间泄漏 1 2 3 4 5 6 7 8 9 在使用由不同版本 Python 编写的代码时,还有一个很有意思的地方。 from __future__ import print_functiona = [i for i in range (10 )] print (i)如果我们在 Python 2 解释器上运行这段代码,我们会得到结果 9 ,因为用于列表推导式的 i 变量留在了内存中。如果你在下部分代码中忘了这回事,再使用 i 变量的话,会导致不可见的错误。 在 Python 3 中一切更为简单,在这个例子中的变量只在列表的创建期间使用,之后不再保存。这样当我们运行代码时,就会看到如下结果: NameError: name 'i' is not defined
func.func_name 1 2 3 4 5 func.func_name func.__name__
软件差异 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ModuleNotFoundError: No module named '_bz2' Pandas==0.25 .3 报此错误 更改安装 pandas==0.24 .2 import unioutpython3 中没有 uniout python2 gunicorn -c fdm/base/gun.conf fdm.views:app python3 配置文件必须有 .py 扩展名 gunicorn -c fdm/base/gun.conf.py fdm.views:app 否则报错 !!! !!! WARNING: configuration file should have a valid Python extension. !!! python2 workers = multiprocessing.cpu_count() / 4 + 1 python3 workers 只接受 int 参数 workers = int (multiprocessing.cpu_count() / 4 + 1 )
from module import *
只能用于模块,不能用于函数from .[module] import name
from .[module] import name
是相对导入的唯一正确语法,所有不以.开头的导入都被当成绝对导入
Python2.7 升级到 Python3.6 Python3 自带 2to3 工具: 2to3 -w
文件/文件夹路径
项目代码修改:
2to3
去除 unicode
print
except,err
has_key
list(child_menus.get(menu_id, {}).items()) 字典加 list
raw_input
<>
basestring
hashlib.md5(dataset_name.encode(‘utf-8’) 增加 encode
sys reload 手动去除
cmp
待修改项:
除法运算。 所有 /
项都需要检查
参考链接