函数
函数是组织好的一组代码块,可以实现单一或关联功能的代码段。函数也可以提高应用的模块性以及代码的重复利用率。
定义一个函数:
def 函数名(函数参数[可以为空]):
函数体
return (无返回值默认为空)
# 使用函数
函数名(根据函数规定传参)
默认情况,参数和参数名是按函数是声明的定义顺序来执行
在python中,如果要使用一个函数,必须在使用前定义
参数
在python中对函数传递参数需要了解在参数的数据类型是可变对象还是不可变对象。
可变对象:列表,集合,字典
- 在作为参数传递时是会改变其内部数字,还是原来的对象
不可变对象:字符串,元组,整型,浮点型
- 在作为参数传递时,如果改变其内容,会新生成一个对象
不可变对象参数
# 使用id()来查看元素的位置变化
def change(b):
print("第一次位置:", id(b))
b = 10
print("改变后的位置:", id(b))
a = 1
print("原始位置:", id(a))
change(a)
可变对象参数
def change(a):
# 修改列表内容
a.append(4)
print("函数中a:",a)
return
#函数外打印值
a = [1,2,3]
print("函数外:",a)
change(a)
参数调用的几种方法
1.必须参数
- 调用函数时必须要添加的参数
2.关键字参数
- 使用函数参数名赋值后作为参数传递。
- 调用函数时:
function(str[函数中的参数]="参数")
3.默认参数
- 在函数创建是已经定义好的参数,不传递参数默认使用
def fun(a,b=10):
- 调用函数
fun(10)
4.不定长参数
- 在创建函数时,使用一个特定的参数来代表需要传递的参数,可以表示任意长度的参数。
def function([args,_],*var_args_tuple):
其中添加*
的参数会以元组(tuple)方式进行传递同样元组可以为空。- 添加
**var_args_dict
是作为字典来标识不定长参数。- 调用函数
function(10,20,30)
*表示隔开关键字参数
在Python中,函数定义中的*
在参数列表中用作位置参数和关键字参数之间的分隔符。当你看到def my_fun(a, b, c, *, d):
这样的函数定义时,它表示函数my_fun
接受三个位置参数a
、b
、c
,以及至少一个关键字参数d
。
这里的*
并不是d
参数的一部分,而是用来指示在*
之后的所有参数都必须是关键字参数。这意味着在调用这个函数时,你不能通过位置来传递d
的值,而必须使用关键字参数的形式。
这里是一个简单的例子来说明这个函数的用法:
def my_fun(a, b, c, *, d):
print(f"a = {a}, b = {b}, c = {c}, d = {d}")
# 正确的调用方式
my_fun(1, 2, 3, d=4) # 输出: a = 1, b = 2, c = 3, d = 4
# 错误的调用方式(会引发TypeError)
# my_fun(1, 2, 3, 4) # 这里没有使用关键字参数d,而是试图通过位置传递第四个参数
在这个例子中,*
之后的d
参数必须是通过关键字传递的,而a
、b
、c
则可以通过位置参数传递。如果你尝试不通过关键字传递d
(比如直接写my_fun(1, 2, 3, 4)
),Python解释器会抛出一个TypeError
,因为它不知道如何处理这个额外的位置参数。
这种语法在Python中非常有用,特别是当你想要确保某些参数总是通过关键字传递时,或者当你想要让函数接受任意数量的关键字参数(通过**kwargs
)时,但又想在关键字参数之前有一些必须的位置参数。
匿名函数
lambda
表达式创建匿名函数。
- 在表达式中封装的逻辑有限
- 有自己的命名空间,不能访问参数列表以外的参数
lambda[arg1[,aarg2,……argn]]:expression
示例:
# 设置相加
x = lambda a:a+7
print(x(3))
# 两个值相加
sum = lambda sum1,sum2:sum1+sum2
print(sum(2,3))
#封装在函数中
def fun(n):
return lambda a:a*n
#1.调用这个函数
num = fun(2) # 此时只传递了n
#2.调用之前使用的lamdba函数,也就是将a传递过去
print(num(10))
函数的返回return
return可以表示退出这个函数,不带参数表示返回值为None
。
携带参数:
- 一个参数
- 两个以上参数
在python中是可以返回两个以上参数的,相应的需要用相对的变量数来接收。
def fun(a,b):
return a+b,a-b
add,sub = fun(20,10)
print(add,sub)
强制位置参数
在Python中,/
符号在函数定义参数列表中使用时,它前面的所有参数都必须是位置参数,而它后面的参数(如果有的话)则必须是关键字参数。这个特性在Python 3.8及以后的版本中引入,旨在提高函数参数的清晰度和可读性。使用/
可以固定前面的参数只能使用位置参数,不能使用关键字参数,和*
是一样可以控制参数传递方法的。
错误写法
-
将
/
放在所有参数之后或没有参数时使用:def func(/*/, a): # 错误,/*/ 无效,且没有参数在/前 pass
-
在
/
之后使用位置参数:def func(a, /, b): # 错误,b 在 / 之后,应该是关键字参数 pass
-
在
\*args
或\**kwargs
之前使用/
:def func(a, /, *args): # 错误,*args 应该在所有位置参数之后 pass def func(a, **kwargs, /): # 错误,**kwargs 也不能在 / 之前 pass
正确写法
-
在需要的位置参数和关键字参数之间使用
/
:def func(a, b, /, c=None, d=None): print(f"a={a}, b={b}, c={c}, d={d}") # 调用时必须按位置传递a和b,c和d可以是关键字参数 func(1, 2, c=3) # 正确 # func(1, 2, 3) # 错误,因为3被当作b传递,没有提供c和d
-
单独使用
/
来确保所有参数都是位置参数:def func(a, b, /): print(f"a={a}, b={b}") # 调用时必须按位置传递a和b func(1, 2) # 正确 # func(1, 2, c=3) # 错误,因为c不是参数
-
结合
\*args
和\**kwargs
使用(注意/
不能出现在*args
或**kwargs
之前):def func(a, b, *args, c=None, **kwargs): print(f"a={a}, b={b}, args={args}, c={c}, kwargs={kwargs}") # 调用时,a和b必须是位置参数,其他可以是位置参数、关键字参数 func(1, 2, 3, 4, c=5, d=6) # 正确
在这个上下文中,没有直接使用/
与*args
或**kwargs
结合的“正确”写法,因为/
的目的是分隔位置参数和关键字参数,而*args
和**kwargs
已经分别用于捕获任意数量的位置参数和关键字参数。不过,你可以在使用*args
和**kwargs
的同时,在它们之前使用/
来确保前面的参数都是位置参数。