迫于年纪大健忘,写了个简陋的装饰器,转换输入类型 - V2EX
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
imn1

迫于年纪大健忘,写了个简陋的装饰器,转换输入类型

  •  
  •   imn1 Nov 24, 2020 2253 views
    This topic created in 1995 days ago, the information mentioned may be changed or developed.

    首先,是 真 简陋

    自用的,出了问题抽自己嘴巴就行了,但无法对他人负责,所以各位要用就谨慎再谨慎,测试多几遍,尽量只用在基础类型,泛类型或者复杂的类型嵌套估计这个解决不了

    作用:作为装饰器,根据函数的 type hints,相同类型跳过,类型不符就调用 funs 指定函数转换,再传给被装饰的函数。 不建议用在产出环境,当然你能把“真简陋”变为“真完美”,那就另说

    起意:就是健忘,经常忘记以前(三天前就算“以前”)写的函数输出类型,新写个函数,处理字符串输出,却发现传入的是个 int / float,想改某个列表元素,却发现传入是个 tuple,用在这些检查、修改花了不少时间,就想简单套个装饰器,先跑通再说,review 修正留待以后处理

    因为自用,我写的 py 几乎没有对外,所以弄个 @修正就算了,懒得逐个查找更改,如果值不对再查,或者后期要完善代码时,再去掉 @慢慢改

    说明:

    1. 可作为无参数装饰器
    2. varnames 默认 None,就对传入的参数轮询一遍,符合 type hint 的,或者 funs / despatcher 没有的类型跳过。 如果非 None,格式是个字符串列表( list/tuple/set 等),列出需要检查的变量名。 没做递归,所以 args,kwargs 传入的就没用了(这两个也没 type hint 吧?)
    3. despatcher 默认 None,就是预置的 funs,是个 “类型:函数名” 的键值对 dict,可以外部传入。 那些 to 什么的函数我就不提供了,放出来会害死人的,例如我 toStr 直接把列表类型用逗号串起来了,因为几乎只用在 sql 相关的函数,字段名是字串,但总是忘记上一个函数输出的是列表还是字串
    4. checktypes 及 is_instance 是人家写的,这里就不贴了,代码在 https://stackoverflow.com/questions/55503673/how-do-i-check-if-a-value-matches-a-type-in-python 很长看上去也很严谨,我就没详细研究了,伸手了事
    5. type hint 就不用说版本了吧,这个仅在 3.7.5 测试,手头也没更多 py 版本
    6. 有错误请指出,也帮我以后避免引入新问题
    7. 这段代码无版权,各取所需(谁用谁负责),至于前面第 4 点引用的代码,版权自理,我也不清楚
    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 转换输出类型的,因为魔改得太厉害(只有自己能用),害死人的代码就不放出来了,反正目的和思路差不多先跑通再说

    3 replies    2020-11-24 22:13:43 +08:00
    ClericPy
        1
    ClericPy  
       Nov 24, 2020
    以前也做过类似的, 把一个有 type hints 的函数转交互式命令行, 各种类型折腾的, 后来被 pydantic.parse_obj 教做人...
    imn1
        2
    imn1  
    OP
       Nov 24, 2020
    @ClericPy
    搜了几天 type hint 都没遇到这个模块,都算神奇,抽空看看
    ClericPy
        3
    ClericPy  
       Nov 24, 2020
    @imn1 这是圈内最流行那个了(好像 fastapi 带起来的?), 还做了 Benchmark... 现在拿它做 schema 校验好用的一塌糊涂, 能把不符合的类型尝试性去转换, 结果让接手我代码的以为我在写 go.....
    About     Help     Advertise     Blog     API     FAQ     Solana     3090 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 15:08 PVG 23:08 LAX 08:08 JFK 11:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86