Python3相比于Python2有哪些常用变化

Python3相比于Python2有哪些常用变化

由于python的核心团队宣布2020年将停止对python2的支持,所以还没有升级到python3的小伙伴们得抓紧了,正所谓长江后浪推前浪,PY3把PY2拍在沙滩上,这里把python3中一些常用变化罗列出来,标准库的变化比较多这里没有列出来,该部分可参考官方文档。

1、print

print在python3中是作为一个函数存在的,这意味着使用的时候必须加上圆括号()来进行调用

语法:print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)

使用说明:

sep是作为输出objects时用的分隔符

>>> print("hello", "world", sep=" the fucking ")
hello the fucking world

end作为输出结尾的符号,默认为\n

file是想将objects输出到何处,默认输出到stdout,由于print支持输出text string,所以只能输出到任何除了二进制模式的file object,即实现了write(string)方法的对象

with open("test.txt", "a") as f:
    print("hello world", file=f)

flush是用来控制输出到file时的buffer。如果要写入一个文件,flush为False,则必须调用文件对象的close方法后才会将内容输出,如果flush为True则会立马写入文件

>>> f=open("test.txt", "a")
>>> print("hello kitty", file=f, flush=False)
>>> f.close()    #此时才会将buffer写入文件
>>> f=open("test.txt", "a")
>>> print("hello dog", file=f, flush=True)    #立马写入文件
>>> f.close()

2、with 从3.1开始支持多个上下文表达式

with A() as a, B() as b:
    suite
相当于
with A() as a:
    with B() as b:
        suite

3、dict

1>dict的方法items(),keys(),values()不再返回list,而是返回view。view对象类似于软链接,如果dict对象有任何更新,都会体现到view上;view实现迭代器方法,所以可以通过for循环或是转换为list等对象来输出其中的数据

>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
>>> keys = dishes.keys()
>>> values = dishes.values()

>>> # iteration
>>> n = 0
>>> for val in values:
...     n += val
>>> print(n)
504

>>> # keys and values are iterated over in the same order
>>> list(keys)
['eggs', 'bacon', 'sausage', 'spam']
>>> list(values)
[2, 1, 1, 500]

>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['spam', 'bacon']

2>由于上面的更新,dict的dict.iterkeys(), dict.iteritems()dict.itervalues()方法在python3中不再支持,因为没有任何意义

3>dict不再支持haskey()方法,请用 key in dict替代。

4、高阶函数map() filter() 不再返回list,而是返回一个迭代器,因为大部分的数据处理都会以来for循环,所以返回迭代器更加节省内存。如果确实需要list,可以不使用map等函数,直接通过列表推倒式来输出list;或者把map返回的迭代器丢到工厂函数list()中。

5、range()函数返回迭代器,python3中不再支持xrange函数。

6、python3中不再有长整型标识L,在python2中windows系统中如果遇到长整型数据则会自动在末尾添加L标识,python3中不会再有这种区分,全部为int型。

7、比较运算符(<, <=, >=, >)两边的操作数如果没有可比性则会抛出TypeError ,不会再返回False,例如:1 < '', 0 > NoneNone < None ,这意味这python在某些方面也体现出强类型的特性。但是==!= 操作符没有做这方面限制,而且不再支持<>操作符。

8、关于class

1>python3中不再有经典类,默认都为新式类,不必通过显示继承object来声明一个新式类

2>改变声明元类的方式

--------Old----------
class C:
    __metaclass__ = M
    ...
--------New----------
you must now use:
class C(metaclass=M):
    ...

3>super()支持无参数调用,会自动选择正确的类和实例来进行继承操作;如果带参数调用则函数功能没有改变。

9、异常捕获语法改变

----------old----------------
try:
    suite
except exception, e:    #不再支持该种语法
    pass
----------new---------------
try:
    suite
except exception as e:
    pass

10、import

1>from module import *语法只支持模块级别的使用,不能在函数内部使用了

2>所有的相对导入必须加上“.” 如:from .[module] import name,否则会被作为绝对导入处理

11、函数参数不再支持自动拆箱,可能大多数pythoner不会这样使用,不过在某些开源工具的源码中有这样的写法,比如fabric,可以在python3中使用Fabric3代替

----------------old-----------------
def f(a, (b, c)):  #不再支持该种语法  
    pass
--------------new------------------
def f(a, b, c):
    pass

12、新增定义函数时的只支持关键字参数的语法

>>> def f(a, b, *, test=1):
...     pass
...
>>> f(1, 2)
>>> f(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 3 were given
>>> f(1, 2, test=3)

如果向上面这样定义一个函数,则关键字参数必选显示赋值,不能以位置参数的形式赋值。其实不依赖该语法也可以实现同样的效果

>>> def f(a, b, *ignore, test=1):
...     if ignore:        #增加一层对额外位置参数的判断即可
            raise TypeError

不过既然有既定的语法又何必去自己实现,某些情况下DRY原则还是很实用的

13、python3中不再有unicode,只有str与bytes类型,str用来处理text文本数据,bytes用于二进制数据。如果这两种类型数据混用会直接抛出TypeError,可以用str.encode()或者bytes(s, encoding=...)将str转换为bytes,同样可以用bytes.decode()或者str(b, encoding=…)将bytes转换为str。

14、默认的default source encoding改为UTF-8,不用在文件开头声明编码方式了。

15、pyc字节码文件

1>python2中源码编译后生成的字节码文件名称只是在原文件的基础上加了个c,例如:mypython.py对应的字节码文件为mypython.pyc。如果用不同的解释器运行的话,又会重新编译生成一个pyc文件,例如:分布式系统,不同的linux环境可能对应的版本不同,这样的就没有很好的将pyc的作为缓存的目的利用起来,会稍微影响初始化效率。

python3中改善了这一情况,所生成的pyc文件会加上对应的版本信息,例如:mypython.cpython-32.pyc,这样可以提前生成好不同版本的pyc,遇到不同版本的解释器无需再重新编译。可能这种情况很少有人会care,毕竟现在的服务环境对应用版本的控制都比较统一。

2>python2中的pyc文件位置是与源文件在同一目录下,如果有大量源文件,就导致了源文件与字节码文件很混乱那。python3中会将生成的pyc文件放到当前包文件夹下的__pycache__文件夹下,这样极大的方便了管理。

16、python3中不再支持raw_input()函数,以input替代。

17、python3.6新增格式化字符串字面量,以f或者F开头的字符串就可以像format那样使用占位符来格式化

>>> a = 123
>>> f'a is {a}'
'a is 123'
>>> f"{123:b}"
'1111011'
>>> f"{123:#b}"
'0b1111011'
>>> f"{a:#b}"
'0b1111011'

18、python3.3给类、方法、函数、描述器以及生成器新增特殊属性__qualname__,用来显示具有层级关系的名称

>>> class C:
...     class D:
...         def meth(self):
...             pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'

python3中将函数的特殊属性func_name即func_code等都去掉了,如果通过自省方式输出函数名称时推荐使用__name__或者__qualname__

 

总结的不是很全,遇到其他常用的会持续更新。如果要将python2的源码转换为python3的推荐使用自带的2to3工具,上面提到的绝大多数问题都会自动解决。如果要解决同一个源文件对python2和3的兼容问题,则推荐在写代码的过程中结合使用six这个库,很多开源工具都用它来解决兼容问题。

人生苦短,我用python!码字辛苦,转载请注明出处及链接!

Comments are closed.