目录
-
- 摘要
- 一、自定义函数概述
-
- [1.1 什么是自定义函数](#1.1 什么是自定义函数)
- [1.2 自定义函数优势](#1.2 自定义函数优势)
- 二、函数定义
-
- [2.1 基本语法](#2.1 基本语法)
- [2.2 无返回值函数](#2.2 无返回值函数)
- [2.3 多返回值函数](#2.3 多返回值函数)
- 三、参数传递
-
- [3.1 位置参数](#3.1 位置参数)
- [3.2 默认参数](#3.2 默认参数)
- [3.3 可变参数](#3.3 可变参数)
- [3.4 字典参数](#3.4 字典参数)
- 四、作用域
-
- [4.1 局部变量](#4.1 局部变量)
- [4.2 全局变量](#4.2 全局变量)
- [4.3 变量优先级](#4.3 变量优先级)
- 五、递归函数
-
- [5.1 递归基础](#5.1 递归基础)
- [5.2 斐波那契数列](#5.2 斐波那契数列)
- [5.3 尾递归优化](#5.3 尾递归优化)
- 六、高阶函数
-
- [6.1 函数作为参数](#6.1 函数作为参数)
- [6.2 匿名函数](#6.2 匿名函数)
- [6.3 内置高阶函数](#6.3 内置高阶函数)
- 七、函数进阶
-
- [7.1 闭包](#7.1 闭包)
- [7.2 函数缓存](#7.2 函数缓存)
- [7.3 函数组合](#7.3 函数组合)
- 八、实战案例
-
- [8.1 数据处理工具函数](#8.1 数据处理工具函数)
- [8.2 工业计算函数](#8.2 工业计算函数)
- 九、总结
- 参考资料
摘要
本文深入讲解DolphinDB自定义函数开发。从函数定义到参数传递,从返回值到作用域,从递归函数到高阶函数,全面介绍UDF开发的核心方法。通过丰富的代码示例,帮助读者掌握自定义函数开发的核心技能。
一、自定义函数概述
1.1 什么是自定义函数
自定义函数(UDF)是用户根据业务需求编写的函数:
#mermaid-svg-2EyY4Fa8A2lJP96m{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2EyY4Fa8A2lJP96m .error-icon{fill:#552222;}#mermaid-svg-2EyY4Fa8A2lJP96m .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2EyY4Fa8A2lJP96m .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2EyY4Fa8A2lJP96m .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2EyY4Fa8A2lJP96m .marker.cross{stroke:#333333;}#mermaid-svg-2EyY4Fa8A2lJP96m svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2EyY4Fa8A2lJP96m p{margin:0;}#mermaid-svg-2EyY4Fa8A2lJP96m .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m .cluster-label text{fill:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m .cluster-label span{color:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m .cluster-label span p{background-color:transparent;}#mermaid-svg-2EyY4Fa8A2lJP96m .label text,#mermaid-svg-2EyY4Fa8A2lJP96m span{fill:#333;color:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m .node rect,#mermaid-svg-2EyY4Fa8A2lJP96m .node circle,#mermaid-svg-2EyY4Fa8A2lJP96m .node ellipse,#mermaid-svg-2EyY4Fa8A2lJP96m .node polygon,#mermaid-svg-2EyY4Fa8A2lJP96m .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2EyY4Fa8A2lJP96m .rough-node .label text,#mermaid-svg-2EyY4Fa8A2lJP96m .node .label text,#mermaid-svg-2EyY4Fa8A2lJP96m .image-shape .label,#mermaid-svg-2EyY4Fa8A2lJP96m .icon-shape .label{text-anchor:middle;}#mermaid-svg-2EyY4Fa8A2lJP96m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2EyY4Fa8A2lJP96m .rough-node .label,#mermaid-svg-2EyY4Fa8A2lJP96m .node .label,#mermaid-svg-2EyY4Fa8A2lJP96m .image-shape .label,#mermaid-svg-2EyY4Fa8A2lJP96m .icon-shape .label{text-align:center;}#mermaid-svg-2EyY4Fa8A2lJP96m .node.clickable{cursor:pointer;}#mermaid-svg-2EyY4Fa8A2lJP96m .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2EyY4Fa8A2lJP96m .arrowheadPath{fill:#333333;}#mermaid-svg-2EyY4Fa8A2lJP96m .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2EyY4Fa8A2lJP96m .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2EyY4Fa8A2lJP96m .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2EyY4Fa8A2lJP96m .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2EyY4Fa8A2lJP96m .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2EyY4Fa8A2lJP96m .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2EyY4Fa8A2lJP96m .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2EyY4Fa8A2lJP96m .cluster text{fill:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m .cluster span{color:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2EyY4Fa8A2lJP96m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2EyY4Fa8A2lJP96m rect.text{fill:none;stroke-width:0;}#mermaid-svg-2EyY4Fa8A2lJP96m .icon-shape,#mermaid-svg-2EyY4Fa8A2lJP96m .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2EyY4Fa8A2lJP96m .icon-shape p,#mermaid-svg-2EyY4Fa8A2lJP96m .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2EyY4Fa8A2lJP96m .icon-shape .label rect,#mermaid-svg-2EyY4Fa8A2lJP96m .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2EyY4Fa8A2lJP96m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2EyY4Fa8A2lJP96m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2EyY4Fa8A2lJP96m :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 自定义函数
函数定义
参数传递
函数体执行
返回结果
函数类型
标量函数
聚合函数
高阶函数
1.2 自定义函数优势
| 优势 | 说明 |
|---|---|
| 代码复用 | 避免重复代码 |
| 模块化 | 逻辑清晰易维护 |
| 可扩展 | 灵活扩展功能 |
| 性能优化 | 向量化计算 |
二、函数定义
2.1 基本语法
python
// 基本函数定义
def functionName(param1, param2, ...) {
// 函数体
return result
}
// 示例:计算两数之和
def add(a, b) {
return a + b
}
// 调用函数
add(1, 2) // 返回 3
2.2 无返回值函数
python
// 无返回值函数
def printInfo(name, value) {
print("名称: " + name + ", 值: " + string(value))
}
// 调用
printInfo("温度", 25.5) // 输出: 名称: 温度, 值: 25.5
2.3 多返回值函数
python
// 多返回值函数
def getStats(data) {
return avg(data), max(data), min(data)
}
// 调用
avgVal, maxVal, minVal = getStats([1, 2, 3, 4, 5])
print("平均值: " + string(avgVal)) // 3
print("最大值: " + string(maxVal)) // 5
print("最小值: " + string(minVal)) // 1
三、参数传递
3.1 位置参数
python
// 位置参数:按顺序传递
def createPoint(x, y, z) {
return [x, y, z]
}
createPoint(1, 2, 3) // [1, 2, 3]
3.2 默认参数
python
// 默认参数
def greet(name, greeting = "你好") {
return greeting + ", " + name + "!"
}
greet("张三") // "你好, 张三!"
greet("张三", "欢迎") // "欢迎, 张三!"
3.3 可变参数
python
// 可变参数
def sumAll(nums...) {
total = 0
for (n in nums) {
total += n
}
return total
}
sumAll(1, 2, 3) // 6
sumAll(1, 2, 3, 4, 5) // 15
3.4 字典参数
python
// 字典参数
def processConfig(config) {
return config
}
processConfig(dict(STRING, ANY, [
["host", "localhost"],
["port", 8848],
["debug", true]
]))
四、作用域
4.1 局部变量
python
// 局部变量:函数内部定义
def calculate(x) {
localVar = x * 2 // 局部变量
return localVar
}
calculate(5) // 10
// localVar // 错误:外部无法访问
4.2 全局变量
python
// 全局变量
globalVar = 100
def useGlobal() {
return globalVar // 可以访问全局变量
}
useGlobal() // 100
4.3 变量优先级
python
// 变量优先级:局部 > 全局
value = 10 // 全局变量
def test() {
value = 20 // 局部变量
return value
}
test() // 20(局部变量)
value // 10(全局变量)
五、递归函数
5.1 递归基础
python
// 递归:阶乘
def factorial(n) {
if (n <= 1) return 1
return n * factorial(n - 1)
}
factorial(5) // 120
factorial(10) // 3628800
5.2 斐波那契数列
python
// 斐波那契数列
def fibonacci(n) {
if (n <= 0) return 0
if (n == 1) return 1
return fibonacci(n - 1) + fibonacci(n - 2)
}
fibonacci(10) // 55
5.3 尾递归优化
python
// 尾递归优化
def factorialTail(n, acc = 1) {
if (n <= 1) return acc
return factorialTail(n - 1, n * acc)
}
factorialTail(100) // 支持大数计算
六、高阶函数
6.1 函数作为参数
python
// 函数作为参数
def apply(func, x) {
return func(x)
}
def double(x) { return x * 2 }
def square(x) { return x * x }
apply(double, 5) // 10
apply(square, 5) // 25
6.2 匿名函数
python
// 匿名函数(Lambda)
def applyLambda(func, x) {
return func(x)
}
applyLambda(def(x) { return x * 3 }, 5) // 15
6.3 内置高阶函数
python
// each:对每个元素应用函数
each(def(x) { return x * 2 }, [1, 2, 3, 4, 5])
// [2, 4, 6, 8, 10]
// map:映射
map(def(x) { return x * x }, [1, 2, 3, 4, 5])
// [1, 4, 9, 16, 25]
// filter:过滤
filter(def(x) { return x > 2 }, [1, 2, 3, 4, 5])
// [3, 4, 5]
// reduce:归约
reduce(def(x, y) { return x + y }, [1, 2, 3, 4, 5])
// 15
七、函数进阶
7.1 闭包
python
// 闭包
def makeCounter() {
count = 0
return def() {
count += 1
return count
}
}
counter = makeCounter()
counter() // 1
counter() // 2
counter() // 3
7.2 函数缓存
python
// 函数缓存(记忆化)
def memoize(func) {
cache = dict()
return def(x) {
if (cache.has(x)) {
return cache[x]
}
result = func(x)
cache[x] = result
return result
}
}
// 缓存斐波那契
fibMemo = memoize(def(n) {
if (n <= 0) return 0
if (n == 1) return 1
return fibMemo(n - 1) + fibMemo(n - 2)
})
fibMemo(50) // 快速计算
7.3 函数组合
python
// 函数组合
def compose(f, g) {
return def(x) {
return f(g(x))
}
}
double = def(x) { return x * 2 }
square = def(x) { return x * x }
doubleThenSquare = compose(square, double)
doubleThenSquare(3) // (3 * 2)^2 = 36
八、实战案例
8.1 数据处理工具函数
python
// ========== 数据处理工具函数库 ==========
// 数据标准化
def normalize(data) {
minVal = min(data)
maxVal = max(data)
return (data - minVal) / (maxVal - minVal)
}
// Z-Score标准化
def zscore(data) {
meanVal = avg(data)
stdVal = std(data)
return (data - meanVal) / stdVal
}
// 滑动平均
def movingAverage(data, window) {
result = array(DOUBLE, data.size())
for (i in 0..data.size()) {
if (i < window - 1) {
result[i] = NULL
} else {
result[i] = avg(data[(i-window+1):(i+1)])
}
}
return result
}
// 异常值检测
def detectOutliers(data, threshold = 3) {
meanVal = avg(data)
stdVal = std(data)
return abs(data - meanVal) > threshold * stdVal
}
// 测试
data = [1, 2, 3, 4, 5, 100, 6, 7, 8, 9]
normalize(data)
zscore(data)
detectOutliers(data)
8.2 工业计算函数
python
// ========== 工业计算函数库 ==========
// 温度单位转换
def celsiusToFahrenheit(celsius) {
return celsius * 1.8 + 32
}
def fahrenheitToCelsius(fahrenheit) {
return (fahrenheit - 32) / 1.8
}
// 压力单位转换
def barToPsi(bar) {
return bar * 14.5038
}
def psiToBar(psi) {
return psi / 14.5038
}
// 流量计算
def calculateFlow(velocity, area) {
return velocity * area
}
// 能耗计算
def calculateEnergy(power, hours) {
return power * hours // kWh
}
// OEE计算
def calculateOEE(availability, performance, quality) {
return availability * performance * quality * 100
}
// 测试
celsiusToFahrenheit(25) // 77
calculateOEE(0.9, 0.85, 0.95) // 72.675
九、总结
本文详细介绍了DolphinDB自定义函数开发:
- 函数定义:基本语法、返回值
- 参数传递:位置参数、默认参数、可变参数
- 作用域:局部变量、全局变量
- 递归函数:阶乘、斐波那契、尾递归
- 高阶函数:函数参数、匿名函数、内置高阶函数
- 函数进阶:闭包、缓存、组合
思考题:
- 如何设计可复用的函数?
- 递归和循环如何选择?
- 高阶函数有什么应用场景?