浅谈python2到python3的区别

随着numpy和django相继宣布不再支持python2.x,我想是时候进入python3.x的时代了。那么今天我们就来看看从python2到python3都有什么重大的改进。

1.通过 @ 实现矩阵乘法

1
2
3
4
5
6
7
import numpy as np
X = np.random.rand(2,2)
W = np.random.rand(2,2)
# python2
Y = W.dot(X)
# python3
Y = W @ X

2.类型提示 → 运行时的类型检查

python在给别人阅读时,有个最大的困扰,就是参数传递类型不明确,给读者造成很大困扰,在python3中加入了type hinting,具体操作如下

1
2
def test(a:int,b:str)->int:
pass

这种写法和scala的写法极其相似,也不知道是谁模仿的谁

1
2
def test(a:Int,b:String):Int={
}

可以看出,指定了a的类型为int,b的类型是str,返回类型为int
但是这种写法仅仅是增加可读性,优化IDE的提示效果,如果想强制限制类型,
需要安装一个模块enforce

1
pip install enforce

具体限制方法如下

1
2
3
4
5
6
7
8
@enforce.runtime_validation
def foo(text:str)->str:
print(text)
return text
foo("hi") # 正确
foo(1)
# 会报RuntimeTypeError
# 提示 The following runtime type errors were encountered:Argument 'text' was not of type <class 'str'>. Actual type was int.

当然,还可以限制数组里的内容,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import typing # 导入泛型模块
@enforce.runtime_validation
def foo(text:typing.List[int])->typing.List[int]:
print(text)
return text
foo([1]) # ok
foo(['1']) # 报错,提示类型错误

# 可以同时定义2个数据类型
T = typing.TypeVar("T",int,str)
@enforce.runtime_validation
def bar(text:T)->T:
print(text)
return text

bar(1) # ok
bar(True) # 报错,提示类型错误

# 还可以对Callable类型做显示
def test(a:int,b:int)->str:
return str(a*b)

@enforce.runtime_validation
def foo(a: typing.Callable[[int, int], str]) -> str:
return a(5, 6)
foo(test) # ok 因为foo函数的参数限制了Callable类型的参数,test函数与他匹配

3.更丰富的解包功能

请看如下对比

1
2
3
4
5
6
7
8
#python2
a,b,*c = [1],[2],[3],[4]
#SyntaxError: invalid syntax

#python3
a,b,*c = [1],[2],[3],[4]
print(c)
#[[3], [4]]

4.更加简洁的super

现在我们在调用super()的时候,已经不需要传入当前的类名和self了,只需要简单的super()即可完成!

1
2
3
4
5
6
7
8
9
# Python 2
class MySubClass(MySuperClass):
def __init__(self, name, **options):
super(MySubClass, self).__init__(name='subclass', **options)

# Python 3
class MySubClass(MySuperClass):
def __init__(self, name, **options):
super().__init__(name='subclass', **options)

参考文献
https://github.com/kommmy/python3_with_pleasure