我应该如何类型提示用 Python 的
ctypes
定义的外部函数?
我需要重复
restype
和
argtypes
属性中提供的信息吗? 或者是否有一种方法可以使 mypy 以某种方式理解属性?
例如,给定此函数定义:
# Original function definition:
libopus.opus_encode.restype = opus_int32
libopus.opus_encode.argtypes = [oe_p, opus_int16_p, c_int, c_uchar_p, opus_int32]
def opus_encode(st, pcm, frame_size, data, max_data_bytes):
return libopus.opus_encode(st, pcm, frame_size, data, max_data_bytes)
是手动复制类型信息的最佳方法吗?
# Duplicated type specification:
libopus.opus_encode.restype = opus_int32
libopus.opus_encode.argtypes = [oe_p, opus_int16_p, c_int, c_uchar_p, opus_int32]
def opus_encode(st: oe_p,
pcm: opus_int16_p,
frame_size: c_int,
data: c_uchar_p,
max_data_bytes: opus_int32) -> opus_int32:
return libopus.opus_encode(st, pcm, frame_size, data, max_data_bytes)
或者有更好的方法吗?
遗憾的是,无法使 mypy 自动推断出
ctypes
函数的类型信息。因此,
你需要手动复制类型信息
,就像你在第二个例子中做的那样。
虽然重复的信息看起来有些冗余,但这却是目前最有效的方式:
-
清晰明了 : 显式地声明参数和返回值类型使函数签名更容易理解,特别是在处理
ctypes
特有的类型时,例如c_int
和c_uchar_p
。 -
mypy 支持 : mypy 能够理解函数签名中的类型提示,并据此进行类型检查,确保代码的类型安全。
-
文档 : 类型提示也作为函数的文档,使其他人更容易理解如何使用该函数。
为了使代码更简洁,可以考虑使用类型别名:
from ctypes import c_int, c_uchar_p
# 类型别名
OpusEncoder = c_int
OpusInt16Ptr = c_int16_p
OpusUcharPtr = c_uchar_p
libopus.opus_encode.restype = OpusEncoder
libopus.opus_encode.argtypes = [oe_p, OpusInt16Ptr, c_int, OpusUcharPtr, OpusEncoder]
def opus_encode(st: oe_p,
pcm: OpusInt16Ptr,
frame_size: c_int,
data: OpusUcharPtr,
max_data_bytes: OpusEncoder) -> OpusEncoder:
return libopus.opus_encode(st, pcm, frame_size, data, max_data_bytes)
这样可以提高代码的可读性,并减少重复。
总而言之,虽然目前无法避免重复信息,但通过使用类型提示和类型别名,你可以使代码更加清晰易懂,并确保类型安全。
标签:python,ctypes,python-typing,mypy From: 64193271