python 参数一样结果不一样_python的函数参数基础(一)(可能和别人讲的不一样,稍微深入一点)...

先让我说几句废话,函数(java里面叫方法)可能是我们了解python以后最基础的东西了(除了数据结构),写了无数个函数,你真的了解python的函数的设计逻辑以及思想吗?

先上一小段我们最经常写的代码,我简单剖析一下:

1 deffunc_test(x,y,z):2 print(x,y,z)3 returnNone4

5 if __name__ == '__main__':6 func_test(1,y=2,z=3)

上面这个代码很简单,就是定义了一个函数,让这个函数打印传入的三个参数,并且返回一个None,但是我在调用的时候的传参方式很别扭,第一个我没有写x=1,而是直接用的1,第二个参数我是用的y=2,但是第三个我也用的y=3,如果你改成下面这样:

1 deffunc_test(x,y,z):2 print(x,y,z)3 returnNone4

5 if __name__ == '__main__':6 func_test(1,y=2,3)

那么编译器一定会报错,究其原因,是因为python的传参问题,因为python的函数接收参数列表方式有两种,第一种是*args(list),第二种是**kwargs(字典),某些角度上来说,第一个是一位数组,第二个是二维数组,但是如果你在一维数组中间,比如y的这个位置,使用了二位数组的传参方式y=2,那么第三个参数,也必须使用二位数组的传参方式,否则就会报错,但是,如果都不用y=这种方式,而用下面的方式,则不会报错:

1 deffunc_test(x,y,z):2 print(x,y,z)3 returnNone4

5 if __name__ == '__main__':6 func_test(1,2,3)

剖析一下第二段代码,因为如果你在参数列表中间使用y=2,编译器会跳过这个参数,那么*args里面的参数列表就少了一个,原本*args里面应该是三个参数,如果跳过一个变成两个参数,那么这两个参数第一个肯定赋给x了,但是第二个应该赋给y还是赋给z,因为y=2被**kwargs捕获了,所以为了避免混淆,编译器第二个参数以及后面的参数必须被**kwargs捕获。

接下来在加一个东西,就是参数列表的类型,python是可以定义参数列表的类型的,但是由于是动态语言,所以一般情况下,python不会有严格的参数校验,但是有时候,我们还有相关的需求,所以这个时候就需要下面这种定义方式:

1 deffunc_test(x,y:str,z:int,i:list,j:dict,a:bool):2 print(x,y,z,i,j,a)3 returnNone4

5 if __name__ == '__main__':6 func_test(1,'2',3,[1,2],{2:3},True)

看起来有点乱,大概的意思就是x不限定类型,y是str类型,z是int类型,是list类型,j是dict类型,a是bool类型,但是由于python不强制限制类型,最多会在pycharm里面提示你传的参数类型不对,编译器并不会强校验,这个时候,如果某些函数想要有这个功能就要加一个python的魔法小代码了,注解,我这段代码没有加强校验,只会打印,如果加,可以加一个assert:

1 defcheck(fn):2 @functools.wraps(fn)3 def wrapper(*args, **kwargs):4 sig = inspect.signature(fn) #截取函数签名

5 param_map = sig.parameters #获取参数列表的字典

6 param_list = list(param_map.values()) #获取参数列表

7 print(type(param_list[0]))8 for i, v inenumerate(args):9 param =param_list[i]10 if param.annotation is not param.empty and notisinstance(v, param.annotation):11 print(param.name,":",v, "!=", param_list[i].annotation)12 for k, v inkwargs.items():13 if param_map[k].annotation is not inspect._empty and notisinstance(v, param_map[k].annotation):14 print(k,':', v, '!=', param_map[k].annotation)15 return fn(*args, **kwargs)16 returnwrapper17

18 @check19 deffunc_test(x,y:str,z:int,i:list,j:dict,a:bool):20 print(x,y,z,i,j,a)21 returnNone22

23 if __name__ == '__main__':24 func_test(1,2,3,[1,2],{2:3},a=0)

param的类是inspect.Parameter,具体参数可以自行百度,篇幅有限就不写太多了,ParamTer中有annotation这个变量,如果不指定paramter的类型,那么它就是inspect._empty类型,如果定义了类型,就是指定的类型,时间有限,这篇就讲到这里面了,下一篇写一下注解,因为我对注解也不是特别了解,需要深入了解以后才能写东西。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值