python2升级python3遇到的问题记录

python2.7升级python3.5时,遇到的一些问题记录如下:

1. 字符串编码是最大的差别,py2的str为utf8编码,有单独的unicode类型,py3的str本身就是unicode编码,utf8则使用bytes类型。所以在py3里面没有unicode这种类型。以下是升级中遇到最蛋疼的麻烦:

>>> d = {'name': '张三'}

>>> b'name' in d
>>> False

2. s = 'abc',则s[0]为字符串'a';s = b'abc',则s[0]为整数97。

3. 在python2中是python -m SimpleHTTPServer,在python3里是python -m http.server

4. py3里没有xrange,只有range,而且返回为可用于迭代的对象。

5. map() zip() filter()也都返回迭代器对象,而不是列表,要得到列表需要写成list(zip(a,b)),包括dict.keys() dict.values() dict.items(),遍历不再需要写iteritems()了。所以map(lambda x : do_sth(x), [...])是不会依次全部执行的。

6. print支持f'{variable}xxx'写法 (py3.6才添加)

7. py2里的dict有clear()操作,但是list是没有的,如果要清空list,写法是del v[:],而在py3里list也添加了clear()方法。

8. py3里,Exception不能直接用索引取值了,需要使用使用args获利参数元组。即:

a = Exception(errno, errstr)
#py2
errno, errstr = a
#py3
errno, errstr = a.args

9. py3里dict没有has_key()方法,统一使用in表达式。

10. 在py2里有混乱的urllib、urllib2、urllib3,而在py3里全统一到urllib里了:

from urllib.parse import urlencode, parse_qs, urlsplit, quote, unquote

11. 整数除法有很大变化,py2整数相除得到还是整数,就像c/c++里一样,而py3则为小数,跟js类似,如果相除还想得到整数,就需要改成//相除。

12. 原来在py2里,4字节以内的整数类型为int,超过就是long,而py3里没有long类型,只有int,其实就是做了简化统一,而带来的问题是,大量整数计算时,py3要比py2占用更多内存,计算也明显更慢。

13. 在py3里,list的sort()没有cmp参数,而是通过key传入一个函数,为每个item生成一个key,再排序,每个key只生成一次。

14. 在py3里,只有input()来接收用户输入,而在py2里,有input()和raw_input(),其中input()相当于eval(raw_input(prompt))。为避免这种危险的函数,py3中就只有一个了,其input()就等同于py2中的raw_input()

15. 在py2里,file()和open()都是打开一个文件,通常你只关心打开模式为只读、读写,还是追加写,但在py3里,没有了file(),只有open(),而且你常常需要关心是否为二进制读或写,以得到bytes类型,从而提高效率。

16. 在py2里,有StringIO或者性能更好的cStringIO来在内存中做类似文件的读写,通常你需要优先import后者,失败时再import前者,而在py3里,统一到了io模块里,你需要考虑的是使用io.ByteIO还是io.StringIO。

17. 在py2里,你可以写next(iter(l)),或者写成iter(l).next(),但是在py3里,你只能用next(iter(l))。

18. 通常我们不用去管python内部的string intern机制,但intern()函数从py2里的全局函数变成了py3里的sys.intern()函数

19. py2里八进制写法为15==017,在py3里,八进制写法有些怪,为15==0o17

20. py3里的super()比py2里的更为强大,主要是支持无参数模式,而且其定义比较奇特:

super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)

第二个默认参数为参数列表的第一个参数,这样,静态函数时就是cls,非静态函数就是self,这让几乎绝大多数情况下都不需要写参数了,例如如下静态函数重载的例子:

In [6]: class A:
   ...:     name = 'A'
   ...:     @classmethod
   ...:     def run(cls, arg):
   ...:         print(cls.name, arg)

In [9]: class B(A):
   ...:     name = 'B'
   ...:     @classmethod
   ...:     def run(cls, arg):
   ...:         super().run(arg)
   ...:         print(cls.name, arg)

In [11]: B.run('abc')
B abc
B abc

 

发表于 2019年08月30日 16:38   修改于 2020年03月26日 18:45   评论:0   阅读:2123  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo