首先,是 真 简陋
自用的,出了问题抽自己嘴巴就行了,但无法对他人负责,所以各位要用就谨慎再谨慎,测试多几遍,尽量只用在基础类型,泛类型或者复杂的类型嵌套估计这个解决不了
作用:作为装饰器,根据函数的 type hints,相同类型跳过,类型不符就调用 funs 指定函数转换,再传给被装饰的函数。 不建议用在产出环境,当然你能把“真简陋”变为“真完美”,那就另说
起意:就是健忘,经常忘记以前(三天前就算“以前”)写的函数输出类型,新写个函数,处理字符串输出,却发现传入的是个 int / float,想改某个列表元素,却发现传入是个 tuple,用在这些检查、修改花了不少时间,就想简单套个装饰器,先跑通再说,review 修正留待以后处理
因为自用,我写的 py 几乎没有对外,所以弄个 @修正就算了,懒得逐个查找更改,如果值不对再查,或者后期要完善代码时,再去掉 @慢慢改
说明:
import inspect
from functools import singledispatch, wraps, partial
from checktypes import is_instance # 说明 4
def toStr(source)->str:
    return str(source)
def toInt(source)->int:
    return int(source)
def typeshint(func=None, *, varnames=None, despatcher=None):
    if func is None:
        return partial(typeshint, varnames=varnames, despatcher=despatcher)
    funs = { # 说明 3
        int: toInt,
        str: toStr,
        # list: toList,
        # tuple: toTuple,
        # set: toSet,
        # dict: toDict,
    }
    despatcher = despatcher if despatcher else funs
    sig = inspect.signature(func)
    parameters = sig.parameters
    varnames = varnames if varnames else parameters.keys()
    @wraps(func)
    def wrapper(*args, **kwargs):
        varkw = inspect.getfullargspec(func).varkw
        binds = sig.bind(*args, **kwargs)
        for n in varnames:
            annotation = parameters[n].annotation
            var = binds.arguments[n] if n in binds.arguments else kwargs[n]
            if is_instance(var, annotation) or (annotation not in despatcher): continue
            ff = despatcher.get(annotation)
            if n in binds.arguments:
                binds.arguments[n] = ff(var)
            else:
                binds.arguments[varkw][n] = ff(var)
        return func(*binds.args, **binds.kwargs)
    return wrapper
if __name__ == "__main__":
    @typeshint
    def myfunc(a:str, b:int=4, c=0):
        print(type(a), a, b, c)
    myfunc(20, '123', '0') # <class 'str'> 20 123 0
两三事:
python 真是什么都是对象,才发现类型也能做 keys
这个 varnames 报错查了几个小时,就因为最初 sig 是写在 wrapper 里面,在 wrapper 里面用 if varnames is None 就报错,要一起移到 wrapper 外面。唉,水平低,会抄会改不会写……
另外有两个类似的,一个自动适应格式的,例如 json/yaml 转字典、csv 转二维,诸如此类,一个根据 return type hint 转换输出类型的,因为魔改得太厉害(只有自己能用),害死人的代码就不放出来了,反正目的和思路差不多——先跑通再说
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.