函数/方法(高级)
函数参数
函数的定义与调用
- 定义格式:
def 函数名(形参):
函数体
......
复制代码
- 调用格式:
函数名(实参) 实际参数
复制代码
默认参数
默认参数:函数/方法在定义是为形参赋值,对应的形参称为默认参数。 默认参数在调用时如果没有对应的实参,则使用默认值作为该参数的值。
- 默认参数定义格式:
def 函数名(形参1 = 值1,...):
函数体
.....
复制代码
- 调用格式一:
函数名(实参) 使用实参作为形参的值
复制代码
- 调用格式二:
函数名() 使用默认值作为形参的值
复制代码
代码演示
def test (a,b=2):
pritn(a)
print(b)
test(1)
1
2
复制代码
参数格式混用一
def test (c =100,b =200, e =300):
print(c)
print(d)
print(e)
test(3)
3
200
300
def test (b =100, a):
print(a)
print(b)
test(1)
复制代码
-
参数格式混用
-
函数/方法的形参定义顺序(从左向右):a,b,c,x=a,y=2,z=3
-
函数/方法的形参调用传参顺序(从左向右):
-
默认参数可以不传值1,2,3
-
默认参数可以按照顺序传值
-
1,2,3,4(x赋值)
-
1,2,3,4,5(x,y赋值)
-
====1====,2,3,4,5,6(x,y,z赋值)
默认参数应用场景
- 减少函数/方法中大量反复的固定值得传参
- 为用户预留可操作的入口
str.index(str , start, end)
list.pop(index)
复制代码
代码演示
str1 = "hello python"
#shr1.index("???".0.len(str1))
#这个是默认值
print(str1.index("0",6,12))
list1 = [1,2,3]
#list1.pop(len(list1)-1)
#这个是默认值
print(list1.pop())
复制代码
关键字参数
关键字参数:函数/方法在调用时指定参赋值的形参变量名,对应的实参称为关键字参数。
- 关键字参数定义格式:
def 函数名(形参,...):
函数体
...
复制代码
- 调用格式
函数名(形参名 = 实参)
复制代码
代码演示
def test (a =100,b =200):
print(a)
print(b)
test(b = 1)
#执行结果
100
1
复制代码
参数格式混用二
def test (a,b):
print(a)
print(b)
test(b=2,a=1)
复制代码
注意: 实参传值时,关键字参数必须出现在位置数后面 函数/方法调用时每个参数只能赋值一次,为避免同意变量同时使用位置参数和关键字参数赋值,建议不同类别的参数使用固定的策略进行参数赋值。 关键字参数主要是解决默认跳跃赋值的问题
关键字参数应用场景
- 简化多默认参数的函数/方法的调用复杂度
- 降低多默认参数的函数/方法的调用风险
print(value,sep,end,file,flush)
复制代码
print("hello",end=" ")
print("itcast",end=" ")
print("python")
#执行结果
hello itcast python
复制代码
注意: 关键字参数在使用后,直接跳过了某一些默认的参数,后续在使用中,如果设定的方法中有大量的默认参数,而使用的时候期望于改其中一个默认参数的值得时候,哪怕是第一个也建议写关键字参数,避免默认调用产生冲突的尴尬。
可变参数
可变参数: 函数/方法在定义时使用一个形参可以接收调用时传入的任意数量的实参,对应的形参称为可变参数。
-可变参数定义格式:
def 函数名(*形参,...):
函数体
....
复制代码
- 调用格式:
函数名(实参1,...)
复制代码
代码演示
def sun(*args):
sums =0
for num in args:
sums += num
print(sums)
sum(1,2,3,4,5)
#执行结果
15
复制代码
参数格式混用三
*和位置参数的混用
def test(a,b,*args):
print(a)
print(b)
print(args)
for data in args:
print(data)
test("张三",18,"itcast",True)
#执行结果
张三
18
('itcast',True)
复制代码
注: 打印出来的元组全部给了*args
位置参数和可变参数,位置参数一定要在可变参数的前边,位置参数不要的参数,都给可变参数。
def test (*args,c,d):
print(args)
print(c)
print(d)
test(1,2,3,c=4,d=5)
#执行结果
(1,2,3)
4
5
复制代码
注: 在进行定义的时候,关键字参数赋值的东西要放在可变参数的后边.
可变参数工作原理
可变参数是对调用时传入的参数进行自动组包,将用户传入的数据以元组的形式保存并传递给函数/方法。 获取传入的数据同元组的基本操作。 使用中注意事项: 在同一函数/方法参数定义中,==只能定义一个可变参数==。
- 参数格式混用
- 函数/方法的形参定义顺序(从左向右):
- 函数/方法的形参调用传参顺序(从左向右):a,*args,x=1
- 函数/方法的调用规则:1,2,3,4,5,x=2
- 位置参数根据位置和数量进行赋值
- 可变参数接收位置参数后默认参数前的所有制
- 默认参数如需传值使用关键字参数的形式写在可变参数传参的后面
可变参数的应用场景
可变参数应用场景可以完美被元组进行代替
print("a","b","c","d",sep="+")
a+b+c+d
#sep是进行定义参数分割符
复制代码
字典参数
字典参数: 函数/方法在定义时使用一个形参可以接收调用时传入的未定义的关键参数,对应的形参称为字典参数。
- 字典参数定义格式:
def 函数名(**形参,...):
函数体
...
复制代码
- 调用格式:
函数名(未定义变量名 =实参1,......)
复制代码
def test(**kwargs):
print(kwargs)
for key in kwargs.keys():
print(key)
print(kwargs[key])
test(a = 1, b = 2)
#执行结果
{'a':1,'b':2}
a
1
b
2
复制代码
结论: 没有定义关键字的参数,被函数接收以后可以通过**定义出来的字典参数接收到。
参数格式混用四
def tast(a,*args,m=1,**kwargs):
print(kwargs)
#a(位置参数),*args(可变参数)
,m=1(默认参数),放在**kwargs
(字典参数后边都会出现报错的现象。)
复制代码
结论: 原始参数最后面加字典参数
def test(m,**kwargs):
print(m)
print(kwargs)
test(x=1,m=1,y=2)
#执行结果
1
{x:1,y:2}
#注: 这种情况m=1可以随意放置
,**kwargs的取值是test中为明确
定义的剩余值,m=1,有明确定义传值给m的。
复制代码
- 字典参数使用的注意事项:
在同一个函数/方法定义中,只能存在一个字典参数。
- 参数格式混用
- 函数/方法的形参定义顺序(从左向右):
- a,*args,x=1,**kwargs
- 函数/方法的形参调用传参顺序(从左向右):
- 1, 2,3,4,5, x=2, m=1,n=2
字典参数应用场景
'''流水线作业一'''
#要求:两端去空格,小写转大写,按照空格切割字符串,输出字符串,同行输出,间隔使用:
#“hello itcast python" ->HELLO: ITCAST:OYTHIN:
def coderl(str):
#对数据进行处理
str_list = str.split()
renturn str_list
def coder2(str):
#对数据进行处理
#交由下一流水下继续作业
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str)
#提供数据,指定最终处理策略
ste_list =coder2(" hello itcast python ")
for data in str_list:
print(data, end= ": ")
#执行结果:
HELLO: ITCAST: PYTHON:
复制代码
'''流水线作业二'''
def coderl(str):
#对数据进行处理
str_list = str.split()
for data in str_list:
print(data, end= ", ")
def coder2(str):
#对数据进行处理
#交由下一流水下继续作业
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str)
#提供数据,指定最终处理策略
coder2(" hello itcast python ")
#执行结果:
HELLO, ITCAST, PYTHON,
复制代码
'''流水线作业三'''
def coderl(str,end):
#对数据进行处理
str_list = str.split()
for data in str_list:
print(data, end=end)
def coder2(str,end):
#对数据进行处理
#交由下一流水下继续作业
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str,ebd)
#提供数据,指定最终处理策略
coder2(" hello itcast python "," -")
#使用传参形式,控制分割格式
#执行结果:
HELLO- ITCAST- PYTHON-
复制代码
'''流水线作业四'''
def coderl(str,**kwargs):
#对数据进行处理
str_list = str.split()
for data in str_list:
print(data,**kwargs)
def coder2(str,**kwargs):
#对数据进行处理
#交由下一流水下继续作业
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str,**kwargs)
#提供数据,指定最终处理策略
coder2(" hello itcast python ",end="%")
#使用字典参数
#执行结果:
HELLO%ITCAST%PYTHON%
复制代码
- 字典参数应用场景
- 函数/方法多层级调用间的关键字参数传递
- 通过设计可避免字典参数的使用
def call_depth_4(d =10,**kwargs):#d留
print("call_depth_4,d =%d" % d)
def call_depth_3(c =10,**kwargs):#c留,d使用字典参数向后传递
print("call_depth_3,d =%d" % d)
call_depth_4(**kwargs)
def call_depth_2(b =10,**kwargs):#b留,cd使用字典参数向后传递
print("call_depth_3,d =%d" % d)
call_depth_3(**kwargs)
def call_depth_1(a =10,**kwargs):#a留,bcd使用字典参数向后传递
print("call_depth_1,d =%d" % d)
call_depth_2(**kwargs)
call_pedth_1(a=1,b=1,c=1,d=1)
#执行结果
call_depth_1,a = 1
call_depth_2,b = 1
call_depth_3,c = 1
call_depth_4,d = 1
复制代码
字典参数形参操作
def test(**kwargs):
print(kwargs)
#**kwargs 将收到的关键字参数按照参数传递的格式交给函数
# {"a":1,"b":2,"c":3}->a = 1,b = 2,c = 3
#*kwargs对传递过来的所有字典参数中键key进行显示操作
print(*kwargs)
#这个是*实际起到的作用是拆包
test(a = 1,b = 2,c = 3)
#执行结果
{'a':1.'b':2,'c':3}
a b c
复制代码
- 字典参数数据读取
- 获取字典参数中被包装的字典对象
- 形参名 (字典)
- 获取字典参数中被包装的所有未知关键字参数名
- *形参名 (实参格式)
- *容器变量名 (拆包成函数调用的参数)
- 解包字典参数中的数据为关键字参数
- **形参名 (实参格式)
拆包: 所有的数据存储容器均支持拆包,拆包后的数据可以用于保存到对应的变量中,也可以用于作为函数/方法调用的实参。
递归函数
递归函数 是在当前函数体内出现了对自身函数的调用。
- 递归函数制作要点
- 要出现自身调用自身的现象
- 要具有明确的结束标志
# 求1到指定数字的和(100)
def sum(num):
#设置结束标志
if num == 1:
retur
return sum(num-1)+num
print(sum(100))
#执行结果
5050
复制代码
注: 函数调用的==最大层级是1000次==,递归操作很容易突破该层级,使用时要注意。主程序自身占一层,所以在999时就报错了。
匿名函数
def add(a , b):
retun a+b
add = lambda a , b : a + b
#等同上述格式
复制代码
- 匿名函数定义格式:
- 函数名 = lambda 形参 : 返回值
- 匿名函数调用格式:
- 结果 = 函数名(实参)
add = lambda a , b : a + b
c = add(3,4)
print(c)
#执行结果
7
复制代码
result = (lambda a , b : a + b )( 3 , 4 )
复制代码
- 匿名函数定义并调用格式:
- 结果 = (lambda 形参 : 返回值)(实参)
c = (lambda a , b : a + b )( 3 , 4 )
print (c)
#执行结果
7
复制代码
匿名函数注意事项
#1.无参数
f1 =(lambda : 100)()
print(f1)
#执行结果
100
#2多返回值
f2,f3 =(lambda : 3 , 4)()
print(f2)
print(f3)
#不可执行
#3无返回值
x =(lambda : print("hello itcast"))()
print(x)
#执行结果
hello itcast
None
#不成立
#4.数据存储模型
f4 = (lambda :[a**2 for a in range(5) if a % 2 == 0])()
print(f4)
#执行结果
[0,4,16]
复制代码
注意事项:
- 匿名函数可以无参数
- 匿名函数不存在无返回值的结果(None)
- 匿名函数仅能返回单一值,不支持自动组包
- 可以通过返回数据存储模型代替多值
- 数据存储模型支持推导式
引用
- 引用 就是变量指想数据储存空间的现象。
- 相同数据使用同一个空间存储,节约内存占用
- 使用==id==(==数据==)操作获取数据存储的内存空间引用地址
引用---数字
a=1
b=1
print(id(1))
print(id(a))
print(id(b))
print(id(2))
a=2
print(id(a))
#执行结果
1777757200
1777757200
1777757200
1777757232
1777757232
flag1 =True
flag2 = False
print(id(flag1))
print(id(flag2))
flag1=False
print("--------------")
print(id(flag1))
print(id(flag2))
#执行结果
1777266912
1777266944
-------------
1777266944
1777266944
str1 = "a"
str2 = "a"
print(id(str1))
print(id(str2))
str1 = "b"
print(id(str1))
print(id(str2))
#执行结果
2093786795904
2093786795904
2215596460272
2215596461952
复制代码
函数参数类型
- 函数的形参如果接收到的实参是不可变类型,函数的内部操作,不会对外部的实参产生影响。
- 函数的形参吐过接收到的实参是可变类型,函数内部的操作,会对外部的实参产生影响。
def test(a):#a->list1->@两个数据对应的地址 最终a->@两个数据对应的地址
a.append("itcast")#a对地址中的数据进行了操作 a->变化?没有->@两个数据对应的地址
list1 = ["hello"."python"]#list1->@两个数据对应的地址
print(list1)
print("---------------")
test(list1)
print(list1)#输出list1,输出list1的指向->@两个数据对应的地址
#执行结果
['hello','python']
------------
['hello','python','itcast']
复制代码
形参使用默认参数
- 函数的形参如果设置了默认参数,且默认参数为可变类型,在调用时,如果不传递参数值,使用默认参数,则默认参数使用同一个引用地址的数据,不会进行二次初始化。
- 对默认参数的值尽量不要使用可变类型的数据