学习Python(7)Pyhton函数 上
函数概述
在一个完整的项目中,某些功能会被反复使用,那么将这部分功能对应的代码提取出来,当需要使用功能的时候直接使用
本质:对一些特殊功能的封装
优点:
a.简化代码结构,提高应用的效率
b.提高代码复用性
c.提高代码的可读性和可维护性
建议:但凡涉及到功能,都尽量使用函数实现
函数基础
函数 function
关键字 def
作用: 封装某个功能的代码
定义函数
return 返回
1. 终止函数
2. 可以返回结果
3. 如果没有return或return后没有值,则默认会返回None
案例一:
# 求2个数的和
def sum2(a, b):
s = a + b
print(s)
sum2(2, 3)
案例二:
# 求一个年份是否为闰年
def is_leap(year):
if year%4==0 and year%100!=0 or year%400==0:
# print('闰年')
return True
print("我是return后面的代码, 我不会执行")
else:
# print("平年")
return False
r = is_leap(2020)
print(r) # True
if is_leap(10000):
print("366天")
else:
print('365天')
案例三:
# 交换2个变量
# return: 多个值
def change(a, b):
return b, a
r = change(2, 3)
print(r) # (3, 2)
x, y = change(4, 5)
print(x, y) # 5 4
print(change(3,4))
print('*' * 100)
函数的参数
参数: 如果函数所实现的功能涉及到未知项参与运算,此时就可以将未知项设置为参数包括形参和实参
形参: 形式参数, 在函数声明的括号()中, 如:a,b
实参: 实际参数, 在函数调用的括号()中, 如:2,3
位置参数/必需参数
def f1(x, y):
print(x, y)
f1(3, 4)
默认参数
def f2(x, y, z=5):
print(x, y, z)
f2(3, 4)
f2(3, 4, 6)
关键字参数
def f3(x, y, z):
print(x, y, z)
f3(z=3, y=4, x=5)
可变参数/不定长参数
*args: 用来接收任意多个位置参数, 接收一个元组
案例:
def f4(*args):
print(args)
f4(1,2,3)
def f5(x, y, *args, z=7, k=8):
print(x, y, args, z, k)
# 1 2 (3, 4, 5, 6) 70 80
f5(1, 2, 3, 4, 5, 6, z=70, k=80)
**kwargs: 用来接收任意多个关键字参数, 会得到一个字典
def f6(x, y, **kwargs):
print(x, y, kwargs)
# 5 6 {'z': 7, 'k': 8}
f6(5, 6, z=7, k=8)
参数的书写顺序
形参: 位置参数, *args, 默认参数, **kwargs
实参: 位置参数, 关键字参数
案例:
def f7(a, b, *args, c=6, d=7, **kwargs):
print(a, b, args, c, d, kwargs)
# 1 2 (3, 4) 6 77 {'x': 8, 'y': 9}
f7(1, 2)
f7(1, 2, 3, 4, d=77, x=8, y=9)
接收任意参数: 通配参数
def f8(*args, **kwargs):
print(args, kwargs)
# (1, 2, 3, 4){'x': 5,'y': 6}
f8(1, 2, 3, 4, x=5, y=6)
匿名函数
不再使用def这种的形式定义函数,使用lambda来创建匿名函数
特点:
a.lambda只是一个表达式,比普通函数简单
b.lambda一般情况下只会书写一行,包含参数,实现体,返回值
语法:lambda 参数列表 : 实现部分
普通函数和匿名函数区别:
# 普通函数
def f(n):
return n**2
# => 匿名函数
f2 = lambda n: n**2
print( f2(3) )
案例:
# 按照字典中年龄排序
# sort()
l = [
{'name': '鹿晗', 'age': 30},
{'name': '蔡徐坤', 'age': 20},
{'name': '宋小宝', 'age': 40},
{'name': '贾玲', 'age': 35},
{'name': '林志玲', 'age': 41},
]
# 普通函数
def fn(d):
retrun d['age']
l.sort(key=fn)
print(l)
# 匿名函数
def fn(d):
return d['age']
l.sort(key=lambda d:d['age'])
回调函数
fn1: 既是函数名称,也是指向该函数的一个变量
函数调用: 只要是指向函数的变量,都可以调用该函数
案例:
def fn1():
print("hello")
# fn1()
fn2 = fn1
fn2()
# 回调
def fm(x, f): # f=f6=
n = f(x)
print(n)
def f6(m):
m = m+1
return m*m
fm(10, f6)
拓展
# 封装一个sort功能的函数
l = [
{'name': '鹿晗', 'age': 30},
{'name': '蔡徐坤', 'age': 20},
{'name': '宋小宝', 'age': 40},
{'name': '贾玲', 'age': 35},
{'name': '林志玲', 'age': 41},
]
def my_sort(ll, key=None):
# 冒泡排序
for i in range(len(ll)-1):
for j in range(len(ll)-1-i):
left = ll[j]
right = ll[j+1]
if key:
left = key(left)
right = key(right)
if left > right:
ll[j], ll[j+1] = ll[j+1], ll[j]
my_sort(l, key=lambda d:d['age'])
print(l)
l2 = [3, 2, 1, 6, 5, 4]
my_sort(l2)
print(l2) # [1, 2, 3, 4, 5, 6]
匿名多个参数函数
f7 = lambda a,b: a+b
print(f7(3, 4))
值传递和引用传递
值传递:传参的过程中传递的是值,一般指的是不可变的数据类型,int, float, str, tuple, bool, None
引用传递:传参的过程中传递的是引用,一般指的是可变的数据类型,list,dict, set
基本类型赋值: 不关联
a = 10
b = a
a = 20
print(a, b) # 20 10
引用类型赋值: 关联
l1 = [1,2,3]
l2 = l1
l1[0] = 99
print(l1, l2) # [99, 2, 3] [99, 2, 3]
案例:
age = 10
person = {'name': "黄晓明", 'age': 43}
def change_age(age1, person1): # age1=age; person1=person
age1 += 1
person1['age'] += 1
change_age(age, person)
print(age, person)
# 10 {'name': '黄晓明', 'age': 44}
总结:
引用传递本质上传递的是内存地址