python--------函数【定义、调用、传递参数、递归函数】

@[toc]

1.什么是函数

  • 函数(function)由若干条语句组成,用于实现特定的功能
  • 函数的本质就是对功能的封装
  • 一旦定义了函数,就可以在程序中需要实现该功能的位置调用函数
  • 函数名不能重复(没有重载)

2.定义和调用函数

  • 使用def关键字来创建python自定义函数
  • 可以直接使用函数名来调用函数

语法结构:

def 函数名 (参数列表)
    函数体
    return 数据
  • 参数列表可以为空,也可以包含多个参数
  • return 可写可不写,不写默认返回None

<1> 定义一个空函数

def test():
    pass

<2> 无参函数

def test():
    print('in test')
test()

运行结果

in test

==尽管定义了函数,只要不调用函数,那这个函数是不会执行的==

def hh():
    print('hello')
 #没有调用这个函数,该函数不执行

<3> 有参函数 (参数---argument/arg)

def test1(arg):
    print('in test')
test1(1)

def test2(arg):
    print('in test',arg)
    #参数类型没有要求,可以是任意类型
test2(1)
test2('hello')
test2([100,200])

def test3(arg,arg1,arg2):
    print('in test',arg,arg1,arg2)
    # 1-->arg  python-->arg1  [1,2]-->arg2
test3(1,'python',[1,2])

运行结果

in test
in test 1
in test hello
in test [100, 200]
in test 1 python [1, 2]
  • 参数类型没有要求,可以是任意类型
  • 参数的个数没有要求

3. 返回值

def test(arg,arg1,arg2):
    print('in test',arg,arg1,arg2)
    return 1  #返回1
ret=test(1,2,3)   #调用test(1,2,3)函数,然后把返回值给ret变量
print(ret)

运行结果

in test 1 2 3
1

==可以返回任何类型==

def test1(arg,arg1,arg2):
    print('in test1',arg,arg1,arg2)
    return [4,5]
ret=test1(1,2,3)
print(ret)

def test2(arg,arg1,arg2):
    print('in test2',arg,arg1,arg2)
    return [arg,arg1,arg2]
ret=test2(1,2,3)
print(ret)

运行结果

in test1 1 2 3
[4, 5]
in test2 1 2 3
[1, 2, 3]

==如果没有return那么就返回None return|return None |不写==

def test3(arg,arg1,arg2):
    print('in test3',arg,arg1,arg2)
ret=test3(1,2,3)
print(ret)


def test4(arg,arg1,arg2):
    print('in test4',arg,arg1,arg2)
    return
ret=test4(1,2,3)
print(ret)

def test5(arg,arg1,arg2):
    print('in test5',arg,arg1,arg2)
    return None
ret=test5(1,2,3)
print(ret)

运行结果

in test3 1 2 3
None
in test4 1 2 3
None
in test5 1 2 3
None

练习题:

#我们系统函数test6 如果都是整数 那么返回数组[1,2,3]
#如果参数全是字符串 就返回 arg arg1 arg2 'welcome to python'

def test6(arg,arg1,arg2):
    #判断参数的类型
    #isinstance 是系统的 用来判断参数是否是你想要的那个类型
    if isinstance(arg,int) and isinstance(arg1,int) and isinstance(arg2,int):
        return [arg,arg1,arg2]
    if isinstance(arg,str) and isinstance(arg1,str) and isinstance(arg2,str):
        return arg+' '+arg1+' '+arg2
    #如果参数并不都是整数或者并不都是字符串,那就返回'Error'
    return 'Error'
c=test6(1,2,3)
print(c)
c=test6('welcome','to','python')
print(c)
c=test6(1,2,'python')
print(c)

运行结果

[1, 2, 3]
welcome to python
Error

4.形参和实参

形参:

  • 形参变量只有在被调用时才分配内存单元,在调用结束时,即可释放预分配的内存单元
  • 形参只在函数内部有效
  • 函数调用结束返回主调用函数后则不能再使用该形参变量

实参:

  • 实参可以是常量、变量、表达式、函数等
  • 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传递给形参
  • 应预先用赋值,输入等办法是参数获得确定值
def calc(x,y): #x,y是形参
    res=x**y
    return res
c=calc(2,3)   #2,3是实参
#有人想这个不就是 x=2,y=3的赋值操作,那就可以直接输出x,y
#但是不要忘了形参只有在被调用时才分配内存单元
#print(x)   错误
#print(y)   错误
print(c)

运行结果

8

5.函数参数

def test7(name,age,score):
    print(name,age,score)

<1>普通参数

test7('yang',18,80)

运行结果

yang 18 80

==普通参数的参数顺序不能改变==

tset7(18,'yang',80)  是错的

<2> 关键字参数

==顺序可以随便设置==

test7(name='yang',age=18,score=80)
test7(age=18,score=80,name='yang')

运行结果

yang 18 80
yang 18 80

<3> 普通参数和关键字参数混合使用

  • 注意python要求 普通参数和关键字参数如果混合使用那么你必须==先传普通参数,然后再传关键字参数==
test7('yang',18,score=80)
test7('yang',age=18,score=80)
test7(name='yang',age=18,score=80)
#test7('yang',age=18,80)   错误
#test7('yang',70,age=18)    错误  70传给age而后面的参数又给age赋值了一个数,那就没有参数传给score了

运行结果

yang 18 80
yang 18 80
yang 18 80

<4>默认参数

def test8(name,age,score=60):
    print(name,age,score)
#因为已经有一个参数有了默认值,所以我们传入两个参数就可以
test8('yang',18)
#当然也可以传三个参数,但是已经默认的那个参数如果也要传的话,它会自动变为传入的数值
test8('yang',18,70)

运行结果

yang 18 60
yang 18 70

==默认参数后面不能有普通参数==

def test9(name,age=18,score=80):
    print(name,age,score)
test9('yang')
# def test9(name,age=18,score):    错误

运行结果

yang 18 80

<5> 可变长参数

(1) *args

  • *args表示一个可变元组
  • args就是一个元组 元组就是只读的数组/列表
  • 参数名就是args
  • *表示 args里面的参数可变
def test10(*args):
    print(args)
test10(1,2,3)   #可以随便添加参数

运行结果

(1, 2, 3)
def test11(*args):
    print(args,type(args)) #只输出args的值和类型
    value=0
    for i in args: #因为args是一个元组,所以需要遍历才能获取每个元素
        value+=i
    return value
c=test11(1,2,3,4)
print(c)
c=test11()   #没有给args传值
print(c)

运行结果

(1, 2, 3, 4) 
10
() 
0

这个可变参数 前面两个参数v1,v2是默认参数,后面的参数是可变的

def test12(v1,v2,*args):
    print(args,type(args))  #只输出args的值和类型
    value=0
    for i in args:
        value+=i
    return value
c=test12(1,2)    #v1=1,v2=2,没有给args传值
print(c)

运行结果

() 
0
def test13(v1,v2,*args):
    print(args,type(args))   #只输出args的值和类型
    value=0
    for i in args:
        value+=i
    return value
c=test13(1,2,3)    #v1=1,v2=2,args=3
print(c)

运行结果

(3,) 
3
def test14(v1,v2,*args):
    print(args,type(args))   #输出args和args的类型
    value=(v1+v2)    #value不像前两个赋值为0,现在的value已经把v1,v2提前加起来了
    for i in args:
        value+=i
    return value
c=test14(1,2,3)    #v1=1,v2=2,args=3
print(c)

运行结果

(3,) 
6

可变参数传数组/列表
*list1就是args

def test14(v1,v2,*args):
    print(args,type(args))   #输出args和args的类型
    value=(v1+v2)    #value不像前两个赋值为0,现在的value已经把v1,v2提前加起来了
    for i in args:
        value+=i
    return value
list1=[1,2,3,4]
c=test14(1,2,1,100,*list1)   #v1=1 v2=2 1,100,*list1就是args
#上面的相当于拆成 c=test14(1,2,1,100,1,2,3,4)
print(c)
(1, 100, 1, 2, 3, 4) 
114

(2) **kwargs

  • 可变参数处理关键字参数
  • kwargs表示 关键字可变参数
  • *表示普通可变参数(positional 位置参数)
  • ** 表示关键字可变参数
  • kwargs是一个字典
def test15(**kwargs):
    print(kwargs,type(kwargs))
    value=0
    for key in kwargs:
        v=kwargs[key]  #获取字典里的值
        if isinstance(v,int) or isinstance(v,float): #如果v是整数或者是浮点数那就执行下面的加法运算
            value+=v
    return value
test15(name='yang')
c=test15(name=10,b=1,c=2,d=3,e=4,f=100.56)
print(c)

运行结果

{'name': 'yang'} 
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56} 
120.56

==可变参数支持位置参数/普通参数和关键字参数==

def test16(*args,**kwargs):
    print(args)
    print(kwargs)
    value=0
    return  value
c=test16(1,2,3,name=10,b=1,c=2,d=3,e=4,f=100.56)
print(c)

运行结果

(1, 2, 3)
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56}
0
def test17(*args,**kwargs):
    print(args)
    print(kwargs)
    value=0
    #先处理位置参数/普通参数
    for i in args:    #遍历元组
        value+=i
    for i in kwargs:   #遍历字典
        v=kwargs[i]
        value+=v
    return  value
c=test17(1,2,3,name=10,b=1,c=2,d=3,e=4,f=100.56)  #若有字符串的参数还需要判断并不参与加法运算
print(c)

运行结果

(1, 2, 3)
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56}
126.56

参数解开

dict2={'name':10,'b':1,'c':2,'d':3,'e':4,'f':100.56}
tuple2=(1,2,3)
# *tuple2 表示把(1,2,3)---->1,2,3
# **dict2 表示把{'name':10,'b':1,'c':2,'d':3,'e':4,'f':100.56}--->name=10,b=1,c=2,d=3,e=4,f=100.56
#  **的作用就是把dict2从字典转换成关键字参数
c=test17(*tuple2,**dict2)
print(c)

运行结果

(1, 2, 3)
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56}
126.56

6.递归函数

递归特性

  • 必须有一个明确的结束条件
  • 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  • 递归效率不高,递归层次过多会导致栈溢出
  • 在计算机中,函数调用时通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的。所以,递归调用的次数过多,会导致栈溢出
def calc(n):
    print(n)
    if int(n/2)==0:
        return n
    res=calc(int(n/2))
    return res
calc(10)

运行结果

10
5
2
1
def calc1(n):
    print(n)
    if int(n/2)==0:
        return n
    res=calc1(int(n/2))
    return res
res=calc1(10)
print(res)

运行结果

10
5
2
1
1
在这里插入图片描述

res的值就是最后得到的1

递归函数相当于问路,我问1号朋友怎么去目的地,1号不知道他去2号,2号不知道他去问3号,3号说我知道怎么走,这时,我们还要返回正确路线给问路人我,3号告诉2号,2号告诉1号,1号再传达给我

person_list=['小明','小李','小红','小蓝']
def ask_way(person_list):
    print('-'*60)    #打印一条分界线
    if len(person_list)==0:   #到最后一个人还不知道怎么走
        return '没人知道'
    person=person_list.pop(0)  #每次都把列表里的第0个元素删除并赋值给person
    if person=='小红':     #小红知道正确的路线
        return '%s说:我知道路,左走一百米就到了'%person
    print('hi 美女[%s],请问你知道华林在哪吗?'%person) #每当问到一个人就输出这句话
    print('%s回答道:不好意思,我不是很清楚,我帮你问问%s...'%(person,person_list))
    res=ask_way(person_list)   #把继续问的人的结果赋值给res,当结果问到时就一层一层的返回给问路的人,并输出下面的话
    print('%s问的结果是:%res'%(person,res))
    return res
res=ask_way(person_list)
print(res)

运行结果

------------------------------------------------------------
hi 美女[小明],请问你知道华林在哪吗?
小明回答道:不好意思,我不是很清楚,我帮你问问['小李', '小红', '小蓝']...
------------------------------------------------------------
hi 美女[小李],请问你知道华林在哪吗?
小李回答道:不好意思,我不是很清楚,我帮你问问['小红', '小蓝']...
------------------------------------------------------------
小李问的结果是:'小红说:我知道路,左走一百米就到了'es
小明问的结果是:'小红说:我知道路,左走一百米就到了'es
小红说:我知道路,左走一百米就到了

你可能感兴趣的:(python--------函数【定义、调用、传递参数、递归函数】)