signature参数的类型推断
对于signature参数,允许用户传入参数/返回值类型,也允许用户不传入。
- 如果用户传入signature参数,不需要原始Python函数使用类型注解(type hints)语法,此时可以支持及时操作式的注册UDF。
- 如果用户不传入signature参数,推荐对原始Python函数使用类型注解(type hints)语法,此时不能支持及时操作式的注册UDF。
两种方式的区别总结如下:
signature参数 |
含义 |
需要原始Python函数使用类型注解语法 |
支持REPL及时操作 |
---|---|---|---|
用户不传值 |
自动推断(推荐) |
否,但是推荐使用 |
否 |
用户传值 |
指定传值 |
否 |
是 |
此处的及时操作指的是读取–求值–输出循环(Read–Eval–Print Loop, REPL),通常见于Python用户交互式终端(Terminal)中。
类型注解(type hints)语法由Python 3.5引入(PEP 484),在函数定义中,类型注解通过在参数名后加冒号(:)和类型,以及在参数列表末尾使用箭头(->)指定返回类型来实现,示例如下:
def greet(name: str) -> str: return f"Hello, {name}"
from typing import List, Dict, Optional def process_data(data: List[int]) -> Dict[str, Optional[int]]: return {"max": max(data) if data else None}
对于Scalar Python UDF,注册时要求强数据类型,所有的参数/返回值都需要指定类型。如果用户不能通过原始Python函数的类型注解语法来指明,那么就需要用户主动使用signature参数指定ibis DataType。
对于Builtin Python UDF,注册时不要求强数据类型(因为数据库中已经注册了该UDF函数)。如果用户不能通过原始Python函数的类型注解语法来指明,那么推荐用户只写出参数名称,不写出类型;如果用户后续用到Builtin Python UDF的返回值(非Top SELECT UDF),那么需要指明函数返回值类型,必要时需要用户主动使用signature参数指定ibis DataType,如果不需要(Top SELECT UDF)则允许用户不写出函数返回值类型。
对于用户不传入signature参数,依赖自动推断时的总结如下:
注册UDF类型 |
参数类型 |
返回值类型 |
---|---|---|
Scalar Python UDF |
需要类型注解(type hints)语法指定。 |
需要类型注解(type hints)语法指定。 |
Builtin Python UDF |
可以只写出参数名称,不写出类型。 |
后续使用返回值时需要类型注解(type hints)语法指定,否则不需要。 |
对于用户不传入signature参数,自动推断的情况,底层实现原理是inspect.signature。目前,接受用户传入以下参数/返回值类型:
Python类型 |
ibis DataType类型 |
对应DataArtsFabric SQL类型 |
---|---|---|
DataType |
DataType |
- |
type(None) |
null |
NULL |
bool |
Boolean |
BOOLEAN |
bytes |
Binary |
BYTEA |
str |
String |
TEXT |
numbers.Integral |
Int64 |
BIGINT |
numbers.Real |
Float64 |
DOUBLE PRECISION |
decimal.Decimal |
Decimal |
DECIMAL |
datetime.datetime |
Timestamp |
TIMESTAMP/TIMESTAMPTZ |
datetime.date |
Date |
TIMESTAMP |
datetime.time |
Time |
TIME |
datetime.timedelta |
Interval |
INTERVAL |
uuid.UUID |
UUID |
UUID |
class |
Struct |
STRUCT |
typing.Sequence, typing.Array |
Array |
ARRAY |
typing.Mapping, typing.Map |
Map |
HSTORE |
注意事项:
- Python内置int类型属于numbers.Integral的子类。
- Python内置float类型属于numbers.Real的子类。
上表中没有列出的Python类型,都是目前暂时不支持的自动转化类型。
对于用户不传入signature参数,同时也没有写出Python类型注解(type hints)语法的参数/返回值,目前自动推断采取如下的方式处理:
参数类型 |
生成匹配Pattern |
Pattern效果 |
---|---|---|
POSITIONAL_ONLY, KEYWORD_ONLY, POSITIONAL_OR_KEYWORD |
ValueOf(None) |
免除__signature__.validate。 |
VAR_POSITIONAL |
TupleOf(pattern=pattern) |
for-loop执行pattern。 |
VAR_KEYWORD |
DictOf(key_pattern=InstanceOf(str), value_pattern=pattern) |
for-loop执行pattern。 |
Return |
ValueOf(Unknown) |
提供UnknowScaclar, UnknownColumn作为UDF返回值向上返回。 |
inspect.signature对于参数类型(Parameter.kind)的分类如下:
参数类型 |
含义 |
示例代码 |
满足条件的参数 |
---|---|---|---|
POSITIONAL_ONLY |
仅限位置参数。 |
def func(a, /, b): pass |
a |
KEYWORD_ONLY |
仅限关键字参数。 |
def func(a, *, b): pass |
b |
POSITIONAL_OR_KEYWORD |
位置或关键字参数。 |
def func(a, b): pass |
a, b |
VAR_POSITIONAL |
可变位置参数。 |
def func(*args): pass |
args |
VAR_KEYWORD |
可变关键字参数。 |
def func(**kwargs): pass |
kwargs |