Julia机器核心编程.多重分配
在开始深入探讨多重分派这个主题之前,我们先问自己一个简单的问题:分派到底是什么意思?用最简单的术语来解释,分派的意思就是发送!
在编程术语中,分派意味着向监听器发送一条消息或者调用一个函数。基本上就是将一段数据(或信息包)发送给准备用来处理它的代码。
分派有多种不同的类型,下面列举出其中的一部分:
• 静态分派:在编译时定义分派的顺序。事实上,在静态分派中,在程序执行之前所有类型都是已知的。编译器能够为每种可能的数据类型组合生成特定的代码,并提前知道它们的使用时间和位置。这是大多数语言中最常用的一种分派方式。举例来说,如果我们在代码的某个位置使用funct()或x.funct()调用函数或者方法,那么每次都会调用相同的函数或者方法,不会有任何变化
• 动态分派:可以在运行时定义分派顺序,这就意味着编译器必须拥有一个包含所有已定义函数的查找表,然后确定运行时实际调用哪些函数。用代码解释的话,假设有类classA和classB,并且它们各自都有一个名为foo()的函数实现,那么在运行时将检查这两个类,最后classA.foo()和classB.foo()的其中一个将会被调用。
• 多重分派:在多重分派中,分派顺序取决于函数名称以及所传递的参数类型,即函数的签名和被调用的实际实现是在运行时直接确定的。用代码解释的话,假设有一个类classA,它实现了一个方法foo(int),参数类型是一个整数,同时实现了另一个方法foo(char),参数类型是字符型。接下来,我们在程序中使用classA.foo(x)进行一次函数调用,在运行时检查将classA和x的类型,从而确定究竟应该调用哪一个foo()函数。
Julia支持多重分派,下面探讨Julia是如何实现此技术的。
方法是Julia生态系统中非常重要的一部分,为了更好地理解多重分派是什么,以及Julia使用多重分派的原因,我们首先需要知道方法是什么。
假设有一个对两个数字求和的函数。范例如下:
代码01~03行定义了求和函数,传入的参数类型被限制为整型。
这里我们定义了add_numbers()函数,它可以接收两个整型参数。当调用add_numbers(1,2)函数时,我们将会得到以下结果:
int64
就和我们预期的结果一样,1+2=3。另外,我们注意到ans的类型,也和所预期的一样是Int64。
但是如果不小心给函数传递了浮点数:
Julia将抛出一个错误!为什么?
答案很简单,因为在函数体中已经明确定义了会传递给add_numbers()函数两个Int64类型的参数。如果没有明确定义这两个参数必须是整数类型,那么就不会抛出错误,如下所示。
这似乎与Python中的函数用法非常相似,在Python中我们只是定义函数,并没有指定参数的类型,而是将推理参数类型的工作留给了Python解释器来做,Julia在这里所做的工作和Python解释器是一样的。
但是,这是否意味着我们之前对参数进行明确的类型定义是错误的呢?答案是否定的!
给函数指定所期望的参数类型会使它们运行得更快,因为编译器不用再推断提供给函数的参数的类型了。记住自己的写法,会提升性能,减少开销通过指定参数类型不仅可以防止编译器浪费时间,而且还可以获得速度上的提升。
我们回到函数add_numbers(num1::Int64,num2::Int64)上,在保证输入参数的类型是整数的情况下,如果想要这个函数返回一个Float类型的对象,该怎么办呢?一种方法是使用convert函数,它会对所传入的参数进行类型转换。convert函数可以接收两个参数,第一个参数是要转换成的数据的类型;第二个参数是准备转换的数据。
01 julia> function add_numbers(num1::Int64, num2::Int64)
02 float_num1 = convert(Abstract Float, num1)
03 float_num2 = convert(Abstract Float, num2)
04 return float_num1+float_num2
05 end
06 add_numbers (generic function with 1 method)
07
08 julia> add_numbers(4,6)
09 10.0
结果是正确的,但不是我们想要的。我们想要的是,即使提供了Float参数,也可以让add_numbers函数起作用。为了解决这个问题,我们再定义一个处理Float64类型数据的方法。
对两个浮点数求和
本例中定义了add_numbers函数用来对两个浮点数求和。
01 julia> function add_numbers(num1::Float64, num2::Float64)
02 return num1+num2
03 end
04 add_numbers (generic function with 2 methods)
05
06 julia> add_numbers(222.0,333.0)
07 555.0
与对两个整数求和的函数的唯一区别就是,我们限制所传入的参数类型为浮点型。如果细心的话,我们会发现在代码04行第一次出现了(generic function with 2 methods)。这是因为这两个函数是同名函数,只不过所传入的参数不同,那么这时新构建的用于计算两个浮点数的和的函数,就会自动成为add_numbers函数下的一个子方法。同时,之前定义的计算两个整数的函数也会变成一个子方法,这两个方法共享add_numbers函数名。
要查看函数自身的所有方法,我们可以使用methods函数。
method函数的使用
01 julia> methods(add_numbers)
02 # 2 methods for generic function "add_numbers":
03 [1] add_numbers(num1::Float64, num2::Float64) at REPL[2]:2
04 [2] add_numbers(num1::Int64, num2::Int64) at REPL[1]:2
仔细观察输出结果,它列出了到目前为止我们为函数定义的所有方法,包括处理两个整型参数的方法和处理两个浮点型参数的方法。
像这种多个子方法对应相同的函数名,并在调用时自动由Julia根据所传递的参数类型来调用相应方法的机制,就是我们所说的多重分派。
- 碎片化 | 第四阶段-39-Struts2中session对象梳理-视频
- 用深度神经网络处理NER命名实体识别问题
- 碎片化 | 第四阶段-40-Struts组件分类讲解-视频
- nginx location配置
- 碎片化 | 第四阶段-41-struts2字节流生成验证码-视频
- Python|模块,包,标准模板
- 人脸识别应用之“变脸”
- 碎片化 | 第四阶段-32-Struts2列表展示-视频
- Angularjs中UI Router超级详细的教程{{下}}
- 碎片化 | 第四阶段-33-Struts2-Spring整合环境概述讲解-视频
- 碎片化 | 第四阶段-34-Struts2-Spring重构项目案例-视频
- Python|高阶函数
- OpenCV特征点检测——ORB特征
- 智能图片压缩-腾讯智图
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- linux安装redis和mysql的实例讲解
- tomcat服务器如何配置字符集为utf-8彻底解决中文乱码的问题详解
- Linux下Android开发环境搭建的操作方法
- liunx 时间函数与时间格式与字符串之间的转化方法
- 详解linux下的.net/mvc/cms程序结构
- Azure给ubuntu虚拟机挂载数据盘的详细步骤
- 详解SSH 远程执行任务的方法
- Linux基础学习之文件查找find的常见用法
- Linux基础之xargs命令的入门实例
- CentOS 7.4下安装Oracle 11.2.0.4数据库的方法
- CentOS桌面环境中网卡启动失败的解决方法
- 浅谈Linux vfork与fork简单对比分析
- Linux定时任务Crontab的使用方法
- linux虚拟网络设备之vlan配置详解
- Centos7安装完后无法联网的解决方法