python3类型提⽰_Python3类型提⽰Python3类型提⽰
本⽂环境基于 Python3.6.4。 通过 EPE483和EPE484两个版本,从Python3.5 开始⽀持类型提⽰(Type Hint)。
简单的例⼦
代码1-1: Python3.5之前⽅法定义
def say_hi(name):
return "Hi,"+name
代码1-2:Python3.5之后的⽅法定义
def say_hi(name:str)->str:
return "Hi,"+name
Python 与 动态语⾔
Python作为动态语⾔, 其设计本意体现了简洁的哲学,这⼀点从import this就可以看出。
代码2-1 Python之禅
> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
所谓动态语⾔,从上来看,
⼀类在运⾏时可以改变其结构的语⾔:例如新的函数、对象、甚⾄代码可以被引进,已有的函数可以被删除或是其他结构上的变化。⽐如众所周知的ECMAScript(JavaScript)便是⼀个动态语⾔。除此之外如Ruby、Python等也都属于动态语⾔,⽽C、C++等语⾔则不属于动态语⾔。
⽽动态类型语⾔的最⼤特点也就是只会在运⾏期间检查数据类型,不⽤给变量特定的类型,最具代表性的也就是
Javascript,Ruby,Python了。
代码2-2
def quack(param):
return param+' is quacking'
上述代码只会在运⾏期间,Cython解释器做类型检查。
静态类型语⾔会在运⾏前(⽐如:编译期间)判断数据类型,例如Java,C#。
代码2-3
private String quack(String param){
return param+' is quacking';
}
同样上述Java代码会在编译时就会对参数和返回值做检查,如果不⼀致,则会导致编译错误。
由以上综述可见,我们解释为什么Python设计原则Simple is better than complex.。动态类型语⾔没有强制类型检查保证了Python语法的简洁,与此同时动态语⾔在运⾏时的类型检查也是影响Python运⾏效率的⼀个因素,也给IDE做类型检查时产⽣了挑战。
⽽动态语⾔典型的风格便是鸭⼦类型。
鸭⼦类型(duck typing)
鸭⼦类型(Duck Typing),是动态类型语⾔的⼀种风格。“当看到⼀只鸟⾛起来像鸭⼦、游泳起来像鸭⼦、叫起来也像鸭⼦,那么这只鸟就可以被称为鸭⼦。”在这种风格中,对象不取决于继承的类或是实现的接⼝,⽽是关注对象可以调⽤的⽅法或是属性。
代码3-1 鸭⼦类型
# 鸭⼦类型
class Animal(object):
def run(self):
print("Animal is running")
class Dog(object):
def run(self):
print("Dog is running")
class Cat(object):
python新手代码useriddef run(self):
print("Cat is running")
def in_the_forest(param):
param.run()
def duck_type():
animal = Animal()
dog = Dog()
cat = Cat()
in_the_forest(animal)
in_the_forest(dog)
in_the_forest(cat)
if __name__ == '__main__':
duck_type()
代码3-1所⽰,对象animal,dog,cat没有实现或者继承关系,都拥有run⽅法,在in_the_forest⽅法中分别传⼊animal,dog,cat对象,调⽤run⽅法,各个对象分别表现出不同的状态。
代码3-2 鸭⼦类型实现多态
# 动态语⾔鸭⼦类型来实现多态
class Animal(object):
def run(self):
print("Animal is running")
class Dog(Animal):
# 重写run ⽅法
def run(self):
print("Dog is running")
class Cat(Animal):
# 重写run ⽅法
def run(self):
print("Cat is running")
def in_the_forest(animal):
animal.run()
def duck_type():
"""鸭⼦类型"""
animal = Animal()
dog = Dog()
cat = Cat()
in_the_forest(animal)
in_the_forest(dog)
in_the_forest(cat)
duck_type()
与代码3-1 对⽐,我们抽象出Animal类,Dog类和Cat类继承Animal,分别重写run⽅法,在in_the_forest⽅法中通过传⼊⽗类Animal来调⽤run⽅法。熟悉Java的同学⼀定可以看出这是Java中多态,其满⾜三个必要条件,继承,重写,⽗类引⽤指向⼦类,所以代码3-2 ⽤鸭⼦类型来实现多态。代码3-3 所⽰,⽤Java代码实现上述功能。
代码3-3 Java模拟鸭⼦类型
// Java通过接⼝实现来模拟鸭⼦类型
interface Animal{
default void run(){
System.out.println("Animal is running");
}
}
public class DuckTyping {
static class Dog implements Animal{
@Override
public void run() {
System.out.println("Dog is runnning");
}
}
static class Cat implements Animal{
@Override
public void run() {
System.out.println("Cat is running");
}
}
private static void inTheForest(T animal){
animal.run();
}
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
inTheForest(dog);
inTheForest(cat);
}
}
Animal dog = new Dog();这段代码中dog对象,在编译期表现的是Animal类型,在运⾏期表现的是Dog类型,⽽Python在运⾏期之前并不会表现出任何类型,所以代码3-2使⽤鸭⼦类型来实现多态显得鸡肋,还不如直接使⽤鸭⼦类型(代码3-1)来得简洁明了。
代码3-3,我们可以做以下修改,通过反射推断⼊参对象是否存在可调⽤的⽅法,使得更加符合鸭⼦类型,
代码3-4
private static void inTheForest(Object object)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
}
但是我们再也⽆法判断inTheForest中参数object类型,也很难对⼊参作出约束。所以说鸭⼦类型放弃类型检查,完全依赖程序员通过⽂档,注释来弹性约束。
使⽤
通过 EPE483和EPE484两个版本建议,从Python3.5 开始⽀持类型提⽰(Type Hint)。我们可以在typing包中到所需的类型。
1. 基本⽤法
def say_greeting(name:str)->str:
return "Hi,"+name
say_greeting("jian")
2. 类型别名
from typing import List
Vector = List[float] # 定义List别名
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
print(scale(0.5, [1.3, 1.2, 1.2, 1.0]))
3.List,Dict,Tuple
from typing import Dict, Any, Tuple, List
MyDict = Dict[str, Any]
MyTuple = Tuple[str, int]
MyList = List[str]
def show_dict(my_tuple: MyTuple, my_dict: MyDict, my_list: MyList) -> None:
assert (isinstance(my_dict, dict))
assert (isinstance(my_tuple, tuple))
print(my_dict)
print(my_tuple)
show_dict(my_tuple=("1", 1), my_dict={'1': 1}, my_list=["1", "2"])
4. NewType
from typing import NewType
UserId = NewType("UserId", int)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论