目录
-
- 摘要
- 一、函数基础
-
- [1.1 函数定义语法](#1.1 函数定义语法)
- [1.2 函数组成部分](#1.2 函数组成部分)
- [1.3 返回值](#1.3 返回值)
- 二、参数传递
-
- [2.1 位置参数](#2.1 位置参数)
- [2.2 默认参数](#2.2 默认参数)
- [2.3 可变参数](#2.3 可变参数)
- [2.4 参数类型检查](#2.4 参数类型检查)
- 三、高级特性
-
- [3.1 闭包](#3.1 闭包)
- [3.2 高阶函数](#3.2 高阶函数)
- [3.3 递归函数](#3.3 递归函数)
- [3.4 函数重载](#3.4 函数重载)
- 四、匿名函数与Lambda
-
- [4.1 匿名函数](#4.1 匿名函数)
- [4.2 部分应用](#4.2 部分应用)
- [4.3 函数组合](#4.3 函数组合)
- 五、工业物联网实战案例
-
- [5.1 设备状态判断函数](#5.1 设备状态判断函数)
- [5.2 设备健康评分函数](#5.2 设备健康评分函数)
- [5.3 异常检测函数](#5.3 异常检测函数)
- [5.4 数据质量检查函数](#5.4 数据质量检查函数)
- 六、模块化编程
-
- [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 断言检查)
- [8.3 异常处理](#8.3 异常处理)
- 九、最佳实践
-
- [9.1 函数设计原则](#9.1 函数设计原则)
- [9.2 代码示例](#9.2 代码示例)
- 十、总结
- 参考资料
摘要
本文深入讲解DolphinDB自定义函数的开发技巧,从基础函数定义到高级特性应用。详细介绍参数传递、返回值处理、闭包、递归、函数重载等核心概念,并提供工业物联网场景的实战案例。同时涵盖模块化编程、函数库管理、性能优化等最佳实践,帮助读者构建高效可复用的函数库。本文适合需要在DolphinDB上进行应用开发的工程师阅读。
一、函数基础
1.1 函数定义语法
DolphinDB使用 def 关键字定义函数:
python
// 基本函数定义
def add(a, b) {
return a + b
}
// 调用函数
add(1, 2) // 3
add(1.5, 2.5) // 4.0
1.2 函数组成部分
函数结构
def关键字
函数名
参数列表
函数体
返回值
1.3 返回值
python
// 单返回值
def square(x) {
return x * x
}
square(5) // 25
// 多返回值
def stats(v) {
return avg(v), max(v), min(v), std(v)
}
a, m, n, s = stats(1..100)
// a=50.5, m=100, n=1, s=28.866
// 无返回值
def printInfo(msg) {
print("INFO: " + msg)
}
printInfo("Hello") // 打印信息,返回void
二、参数传递
2.1 位置参数
python
// 位置参数(按顺序传递)
def createPoint(x, y, z) {
return [x, y, z]
}
createPoint(1, 2, 3) // [1, 2, 3]
2.2 默认参数
python
// 默认参数
def greet(name, greeting="Hello") {
return greeting + ", " + name + "!"
}
greet("DolphinDB") // "Hello, DolphinDB!"
greet("DolphinDB", "Hi") // "Hi, DolphinDB!"
greet("DolphinDB", greeting="Welcome") // "Welcome, DolphinDB!"
2.3 可变参数
python
// 可变参数
def sumAll(...) {
args = getArgs()
total = 0
for (arg in args) {
total += arg
}
return total
}
sumAll(1, 2, 3, 4, 5) // 15
sumAll(10, 20, 30) // 60
2.4 参数类型检查
python
// 类型检查函数
def safeDivide(a, b) {
if (typestr(a) != "DOUBLE" and typestr(a) != "INT") {
throw "参数a必须是数值类型"
}
if (typestr(b) != "DOUBLE" and typestr(b) != "INT") {
throw "参数b必须是数值类型"
}
if (b == 0) {
throw "除数不能为0"
}
return a / b
}
safeDivide(10, 2) // 5
safeDivide(10, 0) // 抛出异常
三、高级特性
3.1 闭包
闭包是指函数可以访问其外部作用域的变量:
python
// 闭包示例
def makeMultiplier(factor) {
// 返回一个函数,该函数可以访问外部的factor变量
return def (x) {
return x * factor
}
}
double = makeMultiplier(2)
triple = makeMultiplier(3)
double(5) // 10
triple(5) // 15
3.2 高阶函数
高阶函数是指接受函数作为参数或返回函数的函数:
python
// 高阶函数:接受函数作为参数
def applyTwice(f, x) {
return f(f(x))
}
def addOne(x) { return x + 1 }
applyTwice(addOne, 5) // 7
// 高阶函数:返回函数
def makeAdder(n) {
return def (x) { return x + n }
}
add5 = makeAdder(5)
add5(10) // 15
3.3 递归函数
python
// 递归计算阶乘
def factorial(n) {
if (n <= 1) return 1
return n * factorial(n - 1)
}
factorial(5) // 120
// 递归计算斐波那契数列
def fibonacci(n) {
if (n <= 1) return n
return fibonacci(n - 1) + fibonacci(n - 2)
}
fibonacci(10) // 55
// 尾递归优化版本
def factorialTail(n, acc=1) {
if (n <= 1) return acc
return factorialTail(n - 1, n * acc)
}
factorialTail(100) // 100!
3.4 函数重载
DolphinDB不支持传统函数重载,但可以通过参数判断实现:
python
// 通过参数类型实现"重载"
def process(data) {
type = typestr(data)
if (type == "INT" or type == "DOUBLE") {
return data * 2
} else if (type == "STRING") {
return upper(data)
} else if (type == "VECTOR") {
return data * 2
} else {
throw "不支持的类型: " + type
}
}
process(10) // 20
process("hello") // "HELLO"
process([1, 2, 3]) // [2, 4, 6]
四、匿名函数与Lambda
4.1 匿名函数
python
// 匿名函数定义
f = def (x) { return x * x }
f(5) // 25
// 简写形式(Lambda表达式)
f = def (x) { x * x } // 省略return
f(5) // 25
// 在高阶函数中使用
each(def (x) { x * 2 }, 1..5) // [2, 4, 6, 8, 10]
4.2 部分应用
python
// 部分应用:固定部分参数
def add(a, b, c) {
return a + b + c
}
// 固定第一个参数
add5 = add{5, }
add5(1, 2) // 8
// 固定后两个参数
add10 = add{, 5, 5}
add10(1) // 11
// 固定中间参数
addMiddle = add{, 5, }
addMiddle(1, 2) // 8
4.3 函数组合
python
// 函数组合
def compose(f, g) {
return def (x) { return f(g(x)) }
}
double = def (x) { x * 2 }
increment = def (x) { x + 1 }
doubleThenIncrement = compose(increment, double)
doubleThenIncrement(5) // 11
incrementThenDouble = compose(double, increment)
incrementThenDouble(5) // 12
五、工业物联网实战案例
5.1 设备状态判断函数
python
// 设备状态综合判断
def getDeviceStatus(temperature, humidity, pressure, vibration) {
// 温度状态
tempStatus = iif(temperature > 35, "高温警告",
iif(temperature < 10, "低温警告", "正常"))
// 湿度状态
humidStatus = iif(humidity > 80, "高湿警告",
iif(humidity < 30, "低湿警告", "正常"))
// 压力状态
pressStatus = iif(pressure > 1020, "高压警告",
iif(pressure < 980, "低压警告", "正常"))
// 振动状态
vibStatus = iif(vibration > 4.0, "振动异常",
iif(vibration > 3.0, "振动偏高", "正常"))
// 综合判断
warnings = [tempStatus, humidStatus, pressStatus, vibStatus]
warningCount = sum(iif(warnings != "正常", 1, 0))
if (warningCount == 0) {
return "正常"
} else if (warningCount == 1) {
return "轻微异常"
} else if (warningCount <= 2) {
return "中度异常"
} else {
return "严重异常"
}
}
// 应用函数
getDeviceStatus(38.0, 50.0, 1010.0, 2.0) // "轻微异常"(高温)
getDeviceStatus(38.0, 85.0, 1025.0, 4.5) // "严重异常"
5.2 设备健康评分函数
python
// 设备健康评分计算
def calculateHealthScore(temperature, humidity, pressure, vibration, power) {
// 温度评分(理想值25°C)
tempScore = 100 - abs(temperature - 25) * 2
tempScore = max(0, min(100, tempScore))
// 湿度评分(理想值50%)
humidScore = 100 - abs(humidity - 50) * 0.5
humidScore = max(0, min(100, humidScore))
// 压力评分(理想值1013hPa)
pressScore = 100 - abs(pressure - 1013) * 0.1
pressScore = max(0, min(100, pressScore))
// 振动评分(越小越好)
vibScore = 100 - vibration * 20
vibScore = max(0, min(100, vibScore))
// 功率评分(稳定性)
// 这里假设power是当前功率,理想值300W
powerScore = 100 - abs(power - 300) * 0.1
powerScore = max(0, min(100, powerScore))
// 综合评分(加权平均)
weights = [0.25, 0.20, 0.15, 0.25, 0.15]
scores = [tempScore, humidScore, pressScore, vibScore, powerScore]
totalScore = 0
for (i in 0..5) {
totalScore += scores[i] * weights[i]
}
return totalScore
}
// 批量应用
t = table(
rand(20..30, 100) as temperature,
rand(40..60, 100) as humidity,
rand(1000..1020, 100) as pressure,
rand(0.0..5.0, 100) as vibration,
rand(100..500, 100) as power
)
t[`healthScore] = each(calculateHealthScore,
t.temperature, t.humidity, t.pressure, t.vibration, t.power)
5.3 异常检测函数
python
// 基于Z-score的异常检测
def detectAnomaly(data, threshold=3.0) {
mean = avg(data)
stdDev = std(data)
if (stdDev == 0) {
return false
}
zScore = abs((data - mean) / stdDev)
return zScore > threshold
}
// 批量异常检测
def detectAnomalies(data, window=10, threshold=3.0) {
n = size(data)
result = array(BOOL, n, n, false)
for (i in window..n) {
windowData = data[(i-window+1):(i+1)]
result[i] = detectAnomaly(data[i], threshold) and
detectAnomaly(windowData, threshold)
}
return result
}
// 应用示例
data = rand(100.0, 1000)
data[500] = 500 // 注入异常值
anomalies = detectAnomalies(data)
sum(anomalies) // 异常点数量
5.4 数据质量检查函数
python
// 数据质量检查
def checkDataQuality(table, columns) {
results = table(1:0, `column`total`null_count`null_rate`unique_count`min_val`max_val,
[STRING, LONG, LONG, DOUBLE, LONG, STRING, STRING])
for (col in columns) {
data = table[col]
total = size(data)
nullCount = sum(isNull(data))
nullRate = nullCount * 100.0 / total
uniqueCount = size(distinct(data))
minVal = string(min(data))
maxVal = string(max(data))
results.append!(table(col, total, nullCount, nullRate, uniqueCount, minVal, maxVal))
}
return results
}
// 使用示例
t = loadTable("dfs://sensor_db", "sensor_data")
quality = checkDataQuality(t, `temperature`humidity`pressure)
六、模块化编程
6.1 模块定义
python
// 文件: modules/iot_functions.dos
// 模块声明
module iot_functions
// ========== 状态判断函数 ==========
def getDeviceStatus(temperature, humidity, pressure, vibration) {
tempStatus = iif(temperature > 35, "高温警告",
iif(temperature < 10, "低温警告", "正常"))
humidStatus = iif(humidity > 80, "高湿警告",
iif(humidity < 30, "低湿警告", "正常"))
pressStatus = iif(pressure > 1020, "高压警告",
iif(pressure < 980, "低压警告", "正常"))
vibStatus = iif(vibration > 4.0, "振动异常",
iif(vibration > 3.0, "振动偏高", "正常"))
warnings = [tempStatus, humidStatus, pressStatus, vibStatus]
warningCount = sum(iif(warnings != "正常", 1, 0))
return iif(warningCount == 0, "正常",
iif(warningCount == 1, "轻微异常",
iif(warningCount <= 2, "中度异常", "严重异常")))
}
// ========== 健康评分函数 ==========
def calculateHealthScore(temperature, humidity, pressure, vibration, power) {
tempScore = max(0, min(100, 100 - abs(temperature - 25) * 2))
humidScore = max(0, min(100, 100 - abs(humidity - 50) * 0.5))
pressScore = max(0, min(100, 100 - abs(pressure - 1013) * 0.1))
vibScore = max(0, min(100, 100 - vibration * 20))
powerScore = max(0, min(100, 100 - abs(power - 300) * 0.1))
return tempScore * 0.25 + humidScore * 0.20 + pressScore * 0.15 +
vibScore * 0.25 + powerScore * 0.15
}
// ========== 单位转换函数 ==========
def celsiusToFahrenheit(celsius) {
return celsius * 9 / 5 + 32
}
def fahrenheitToCelsius(fahrenheit) {
return (fahrenheit - 32) * 5 / 9
}
def pascalToBar(pascal) {
return pascal / 100000
}
def barToPascal(bar) {
return bar * 100000
}
6.2 模块使用
python
// 加载模块
use iot_functions
// 使用模块中的函数
status = getDeviceStatus(38.0, 50.0, 1010.0, 2.0)
score = calculateHealthScore(25.0, 50.0, 1013.0, 1.0, 300.0)
fahrenheit = celsiusToFahrenheit(25.0)
6.3 函数库管理
函数库结构
modules/
iot_functions.dos
物联网函数
statistical.dos
统计函数
utils.dos
工具函数
状态判断
健康评分
单位转换
描述统计
假设检验
字符串处理
日期处理
七、性能优化
7.1 向量化优化
python
// 不推荐:循环调用
def processEach(data) {
result = array(DOUBLE, 0)
for (d in data) {
result.append!(d * 2 + 1)
}
return result
}
// 推荐:向量化处理
def processVector(data) {
return data * 2 + 1
}
// 性能对比
data = rand(100.0, 1000000)
// processEach(data) // 慢
// processVector(data) // 快100倍以上
7.2 避免重复计算
python
// 不推荐:重复计算
def badExample(data) {
return avg(data) + max(data) - avg(data) // avg计算两次
}
// 推荐:缓存结果
def goodExample(data) {
avgVal = avg(data)
return avgVal + max(data) - avgVal
}
7.3 使用内置函数
python
// 不推荐:自己实现
def mySum(data) {
total = 0
for (d in data) {
total += d
}
return total
}
// 推荐:使用内置函数
sum(data) // 内置函数经过高度优化
八、调试技巧
8.1 打印调试
python
def debugExample(x, y) {
print("输入参数: x=" + string(x) + ", y=" + string(y))
result = x + y
print("中间结果: " + string(result))
result = result * 2
print("最终结果: " + string(result))
return result
}
8.2 断言检查
python
def safeFunction(data) {
assert(size(data) > 0, "数据不能为空")
assert(typestr(data) == "VECTOR", "参数必须是向量")
result = avg(data)
assert(not isNull(result), "计算结果不能为空")
return result
}
8.3 异常处理
python
def robustFunction(data) {
try {
result = someRiskyOperation(data)
return result
} catch(ex) {
print("错误: " + ex)
return null
}
}
九、最佳实践
9.1 函数设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 单一职责 | 一个函数只做一件事 | calculateAvg() 而非 calculateAll() |
| 命名清晰 | 函数名表达意图 | getDeviceStatus() 而非 check() |
| 参数合理 | 参数数量适中 | 不超过5个参数 |
| 有文档 | 添加注释说明 | 说明参数、返回值 |
9.2 代码示例
python
// 好的函数设计
/**
* 计算设备健康评分
* @param temperature 温度(摄氏度)
* @param humidity 湿度(百分比)
* @param pressure 压力(hPa)
* @param vibration 振动(mm/s)
* @param power 功率(W)
* @return 健康评分(0-100)
*/
def calculateHealthScore(temperature, humidity, pressure, vibration, power) {
// 实现代码...
}
十、总结
本文详细介绍了DolphinDB自定义函数的开发技巧。核心要点如下:
- 函数基础:定义、参数、返回值
- 高级特性:闭包、高阶函数、递归
- 匿名函数:Lambda表达式、部分应用
- 工业应用:状态判断、健康评分、异常检测
- 模块化:模块定义、函数库管理
- 性能优化:向量化、避免重复计算
思考题:
- 如何设计一个可复用的设备状态判断函数库?
- 闭包在工业物联网场景中有哪些应用?
- 如何平衡函数的灵活性和性能?