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

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

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

1 def func_test(x,y,z):
2     print(x,y,z)
3     return None
4
5 if __name__ == ‘__main__‘:
6  func_test(1,y=2,z=3)

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

1 def func_test(x,y,z):
2     print(x,y,z)
3     return None
4
5 if __name__ == ‘__main__‘:
6  func_test(1,y=2,3)

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

1 def func_test(x,y,z):
2     print(x,y,z)
3     return None
4
5 if __name__ == ‘__main__‘:
6  func_test(1,2,3)

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

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

1 def func_test(x,y:str,z:int,i:list,j:dict,a:bool):
2     print(x,y,z,i,j,a)
3     return None
4
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 def check(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 in enumerate(args):
 9             param = param_list[i]
10             if param.annotation is not param.empty and not isinstance(v, param.annotation):
11                 print(param.name,":",v, "!=", param_list[i].annotation)
12         for k, v in kwargs.items():
13             if param_map[k].annotation is not inspect._empty and not isinstance(v, param_map[k].annotation):
14                 print(k,‘:‘, v, ‘!=‘, param_map[k].annotation)
15         return fn(*args, **kwargs)
16     return wrapper
17
18 @check
19 def func_test(x,y:str,z:int,i:list,j:dict,a:bool):
20     print(x,y,z,i,j,a)
21     return None
22
23 if __name__ == ‘__main__‘:
24  func_test(1,2,3,[1,2],{2:3},a=0)

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

原文地址:https://www.cnblogs.com/dutu/p/10917217.html

时间: 2024-07-31 12:46:50

python的函数参数基础(一)(可能和别人讲的不一样,稍微深入一点)的相关文章

python中函数参数的引用方式

值传递和引用传递时C++中的概念,在python中函数参数的传递是变量指向的对象的物理内存地址!!! python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是"传对象引用"的方式.这种方式相当于传值和传引用的一种综合.如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过"传引用"来传递对象.如果函数收到的是一个不可变对象(比如数字.字符或者元组)的引用,就不能直接修改原始对象--相当于通过"传值

Python的函数参数

前言 python中 函数的参数可以分为两大类形参和实参~ def func(x, y): # x, y 就是形参 print(x, y) func(2, 3) # 2, 3 就是实参 - 形参 形参(如上面的x, y)仅在定义的函数中有效,函数调用结束后,不能再使用该形参变量.在调用函数时,该函数中的形参才会被分配内存,并赋值:函数调用结束,分配的内存空间也随即释放~ - 实参 即在调用函数时,向该函数的形参传递确定的值(必须是确定的值).传递的值可以是常量.变量.表达式.函数等形式~ 在形参

python下函数参数的传递(*和**)

1.F(arg1,arg2,...) 这 是最常见的定义方式,一个函数可以定义任意个参数,每个参数间用逗号分割,用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的 值(实际参数),而且顺序必须相同,也就是说在这种调用方式中,形参和实参的个数必须一致,而且必须一一对应,也就是说第一个形参对应这第一个实参.例 如: def a(x,y): print x,y 调用该函数,a(1,2)则x取1,y取2,形参与实参相对应,如果a(1)或者a(1,2,3)则会报错. 2.F(arg

Python 4.函数参数 返回值与文档查看(基础篇)

本章大纲:(以后文笔格式都会在开头有个大纲) -五大参数- 普通参数 默认参数 关键字参数 收集参数 收集参数解包问题 关键字收集参数 关键字收集参数解包问题 -返回值- -文档查看- -普通参数- 普通参数又名为位置参数,没有默认值,根据具体使用位置进行传值 普通参数和默认参数的不同 普通参数就是如同名字一般普通,没有默认值 而默认参数则可以规定默认值(也就是规定了默认值的普通参数而已) 但是默认参数要牢记一点:默认参数必须指向不变的对象值 请看下面例子 def add_end(L=[]):

简单介绍下python中函数的基础语法

python 函数 定义 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可. 特性 减少代码重复 使程序变得可扩展 使程序变得易于维护 函数的创建 python中创建函数,需要使用__def__关键字,后面写函数的名字,然后是形参列表,大体如下: def 函数名(形参列表): 函数体...... return 返回值 其中形参列表和 return返回值并不是必须的. 函数的使用 想要调用函数程序,需要以函数名加括号的形式进行调用,而括号内可以传入参数

Python之函数参数介绍

Python的参数类型: 普通参数 默认参数 动态参数 普通参数 包括:形参和实参 形参就是形式参数,仅仅是写在函数中,并没有赋值和调用它 实参则是执行函数时用到的参数,它在内存中有赋值 例子: test(txt):     txt,test() 输出结果:hello this is a test 这里txt就是形参,'hello'则是实参 默认参数: 默认参数的要求: 1.不传,则使用默认值, 2.默认参数必须放在参数列表最后 calculation(x,y,z=):     x+y+z ca

Python的函数参数和递归参数

位置参数 def power(x): return x*x; 默认参数 指的是在函数定义的时候,就赋予一些参数默认值,在调用这个函数的时候不必多次传入重复的参数值. 如定义一个多次输出同一个年龄阶段和同一个城市的学生的姓名和性别. def info(name,gender,age=20,city='sichuan'): print('name:', name) print('gender:', gender) print('age',age) print('city',city) info("x

python中函数参数*args和**kw的区别

1.函数与参数(实参) 在python中创建函数是def,创建函数名是def f(),f函数名字,def f(a,b),这里的a,b是两个参数,函数名是自定义的,参数也是自定义,随意就好.看图如下效果: 这里f(1,2)是实参,然后调用上面的函数. 下面讲解下*args和**kw的区别. 2.*args 这里的*后面的值是自定义的,只要不是数字就行,定义成*abc,*ccc都可以,len()是函数,它的意思是返回字符串长度.然后前面的a,b是普通参数,print a print b就是回显1,2

Python的函数参数问题

先定义一个带默认参数的函数: def add_end(L=[]): L.append('END') return L 使用下面的代码调用该函数: print(add_end([1,2,3])) print(add_end()) print(add_end([1,2,3])) print(add_end()) 结果: 为什么第四行输出会是这样呢?看了廖雪峰老师的教程后,对此问题的理解为: 在定义完函数后,参数L的值就被计算出来了,并成为了一个类似于“全局变量”的东西,也就是说,一次调用函数完了之后