0%

第三周-函数

函数的参数传递

不可变对象

number, string, turple

函数传参如果传递的是这种类型,无法在函数内改变传入的参数的值

可变对象

list, dict, set

函数传参如果传递的是这种类型,可以在函数内改变传入的参数的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def fun(a):  # a形参
print(f"inside {id(a)}")
a[0] = 100

list = [1, 2, 3, 4, 5]
print(f"outside {id(list)}")
fun(list)
print(list)

def add(num):
print(f"inside {id(num)}")
num += 10

num = 10
print(f"outside {id(num)}")
add(num)
print(f"now num: {num}")

在 Python 中,整数是不可变的(immutable),所以在 add 函数中,执行 num += 10 时,实际上是创建了一个新的整数对象,并将 num 重新指向这个新对象。这并不会影响到函数外部的 num 变量

关键字参数:**args

允许函数调用时参数顺序和定义时不一致

1
2
3
4
5
6
7
8
9
def get_stu_info(name,age,**args):
#print('姓名是:%s,年龄是:%d'%(name,age))
print(name)
print(age)
print(args)
#调用函数
get_stu_info('xiaoming',29,sex='男')
get_stu_info('xiaoming',29,sex='男',height=178,weight=80,hobby='唱歌')

默认参数

调用函数时,缺省参数的值如果没有传入,则会被认为是默认值

不定长参数

加了一个*号的变量args会存放所有未命名的变量参数,----》元祖 加了**号,存放所有命名的变量参数----》字典

加了一个*号的变量args会存放所有未命名的变量参数,----》元祖 加了**号,存放所有命名的变量参数----》字典

1
2
3
4
5
6
7
8
9
10
def fun(a,b,c,*args,**kwargs):
print('a=',a)
print('b=',b)
print('c=',c)
print('args=',args)
print('kwargs=',kwargs)
for key,value in kwargs.items():
print('key=',key,'value=',value)
#调用函数
fun(1,3,5,6,name='鹿晗',age=20,height=180)

output

1
2
3
4
5
a= 1
b= 3
c= 5
args= (6,)
kwargs= {'name': '鹿晗', 'age': 20, 'height': 180}

先后顺序方面一般先*再**

匿名函数

定义:

不使用def这样语句来定义函数 使用lambda来创建一个匿名函数

1
lambda arguments: expression
  • lambda: 关键字,表示定义一个匿名函数。
  • arguments: 参数列表,类似于函数的参数,但不能包含默认值、可变参数等。
  • expression: 单一的表达式,函数的返回值。

应用

作为参数进行传递

1
2
3
4
5
6
def test(a,b,opt): #opt当做参数传递
print(a)
print(b)
print(opt(1,8))
#调用函数
test(10,100,lambda x,y:x+y)

output

1
2
3
10
100
9

作为内置函数的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
stus = [
{"name":"zhangsan","age":18},
{"name":"wangwu","age":20},
{"name":"laowang","age":35}]

#根据名称进行排序
print('排序之前的数据:')
print(stus)
print("按照名称进行排序")
stus.sort(key=lambda y: y['name'])
print(stus)

#根据年龄进行排序
print("按照年龄排序")
stus.sort(key=lambda c: c['age'])
print(stus)

sort 函数接受一个关键字参数 key,这个参数是一个函数或 lambda 表达式,用于指定排序的依据。

lambda y: y['name'] 是一个匿名函数,接受一个字典 y,返回该字典中键为 'name' 的值

1
2
3
4
5
6
排序之前的数据:
[{'name': 'zhangsan', 'age': 18}, {'name': 'wangwu', 'age': 20}, {'name': 'laowang', 'age': 35}]
按照名称进行排序
[{'name': 'laowang', 'age': 35}, {'name': 'wangwu', 'age': 20}, {'name': 'zhangsan', 'age': 18}]
按照年龄排序
[{'name': 'zhangsan', 'age': 18}, {'name': 'wangwu', 'age': 20}, {'name': 'laowang', 'age': 35}]

偏函数

函数在执行时,要带上所有必要的参数进行调用。但是,有时参数可以在函数被调用之前提前获知。这种情况下,一个函数有一个或多个参数预先就能用上,以便函数能用更少的参数进行调用。

可以有效冻结一些预先定义好的参数,对函数参数做缓存,后面想使用再解冻 类似斐波那契数列,知道了前面的几个数,就能推导出后面的数字 比如定义了一个函数,传了2个参数,现在调用可能只会用到部分参数,可以将它冻结起来 后面想使用时候随时解冻

1
2
3
4
5
6
from functools import partial
def add(a,b):
return a + b
plus = partial(add,100) #提前获知第一个参数的值
res = plus(9)
print(res)

使用了 Python 中的 functools.partial 函数来创建一个偏函数

定义了一个原始函数 add(a, b),用于计算两个数之和。

使用 functools.partial 创建了一个新的函数 plus,通过 partial(add, 100),将原始函数 add 的第一个参数 a 固定为 100,这样,plus 函数实际上就是 add 函数的一个变体,其中第一个参数已经被固定为 100

调用 plus(9),相当于调用 add(100, 9),得到结果 109

局部变量和全局变量

如何在函数里修改全局变量:global 全局变量名

1
2
3
4
5
6
7
8
9
10
11
12
x = 10

def test():
# x = 100
# print(x)
global x
x = 1010

#调用函数
print(f"before function:{x}")
test()
print(f"after function:{x}")
1
2
before function:10
after function:1010

当不可变的数据类型作为全局变量,需要用global声明,进行修改 可变的数据类型 不一定

如何在函数里使用外层变量:nonlocal 外层变量名

1
2
3
4
5
6
7
8
9
10
11
12
#nonlocal:使用函数的外层变量
def test():
num = 2
print(f"before test2, num:{num}")
def test2():
nonlocal num
num *= 2
print(f"in test2,num:{num}")
print(f"after test2,num:{num}")
return test2()
#调用函数
test()

装饰器

定义:

本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

这么做目的是:首先把函数传递到装饰器里面,先验证权限,验证通过,再调用传递进来函数

基本格式

@函数名

举例说明

定义一种装饰器函数如下

1
2
3
4
5
6
7
8
def w1(fun):
def inner():
# 验证1
# 验证2
# 验证3
pass
fun()
return inner

定义带装饰器的函数

1
2
3
@w1
def f1():
print('f1')

直接调用装饰器

1
2
3
print("直接调用装饰器")
f = w1(f1)
f()

输出

1
f1

使用被语法糖修饰的带装饰器的函数

1
f1()

输出

1
f1

举例运用

1
2
3
4
5
6
7
8
9
10
11
#定义了一个装饰器函数
def makeBold(fn):
def wrapped():
return '<b>'+fn()+'</b>'
return wrapped
#定义一个带装饰器的函数
@makeBold
def test1():
return 'hello-world-1'
#调用函数
print(test1())

输出

1
<b>hello-world-1</b>