函数定义和调用

函数

函数就是一些列python语句的组合,可以在程序中一次或多次,一般是完成具体的独立功能。

使用函数是为了复用最大化及最小代码冗余,整体代码结构清晰,问题局部化。

函数定义:

def function():
    代码块

函数调用:函数名+()即可调用,本质上就是执行函数定义的代码块,在调用之前,必须先定义。

def my_func():
    print("my name is Mike")
    print("I'm 12 years old")
my_func()
#运行结果
my name is Mike
I'm 12 years old

参数

参数:在定义函数时,在括号定义n个参数(变量),并在调用时给其赋值。

def my_func(name=,age):
    print("my name is %s,"%name,end="")
    print("I'm 12 years %d"%age)
my_func()
my_func("Bob",16)
#运行结果
my name is Bob,I'm 12 years 16

参数的分类:必填参数、默认参数、可选参数、关键字参数。

参数:其实就是函数为了实现某项特定的功能,进而为了得到实现功能所需要的数据。

必填参数

在调用时,必须填写参数,且填写完整(每个参数都要填),否则会报错。

def sum(a,b):       #在这里a和b形式参数(形参),只是意义上的参数,在定义时不占用内存地址
    sum=a+b
    print(sum)
sum(1,2)            #这里的1和2是实际参数(实参),会占用内存地址
#运行结果
3

默认参数

在调用函数时,如果未赋值,就会将默认值赋值给参数,如果有两个以上有默认值的参数,如果在调用时只填写一个参数值,则该值只能赋值给第一个参数。

def sum(a=2,b=3):
    sum=a+b
    print(sum)
sum(1,2)
sum(3)
sum()
#运行结果
3
6
5

可变参数

可传入任意个参数,通过输出发现,参数实际以元组的形式存储。

def flex(*args):
    print(args)
flex((1,2,3,4,5))
flex(1,2,3,4,5)
flex([1,2,3])
#运行结果
((1, 2, 3, 4, 5),)
(1, 2, 3, 4, 5)
([1, 2, 3],)
def flex(*args):
    print(args)
    sum=0
    for items in args:
        sum=sum+items
    print(sum)
flex(1,2)
flex(1,2,3,4,5)
#运行结果
(1, 2)
3
(1, 2, 3, 4, 5)
15

关键字参数

用两个星号定义,在函数体内,参数关键字是一个字典类型的,key是一个字符串,关键字参数可以不赋值。

def keyfunc(**kwargs):
    print(kwargs)
#keyfunc(1,2,3) 不可以运行
dict={"name":"Mike","age":12}
keyfunc(**dict)
keyfunc(name="Peter",age=16)
keyfunc()
#运行结果
{'name': 'Mike', 'age': 12}
{'name': 'Peter', 'age': 16}
{}

参数组合使用

注意:可选参数必须放在关键字参数之前。

def comfunc(*args,**kwargs):
    print(args)
    print(kwargs)
comfunc(1,2,3,4)
comfunc(1,2,3,4,name="mike")
comfunc(age=15)
#运行结果
(1, 2, 3, 4)
{}
(1, 2, 3, 4)
{'name': 'mike'}
()
{'age': 15}

函数返回值

在函数执行完以后要返回一个对象,如果在函数内部有return,就可以返回实际值,否则返回为空。返回值可以返回任意类型,取决于return后面的类型。

在一个函数内可以出现多个return,但是肯定只能返回一个return,如果在一个函数体内执行了return,函数就执行完成退出了,return后面的代码语句将不再执行。

def sum(a,b):
    sum=a+b
    return sum
result=sum(10,20)
print(result)
#运行结果
30

如果不加return

def sum(a,b):
    sum=a+b
result=sum(10,20)
print(result)
#运行结果
None		#返回为空

返回结果可以是任意数据类型,比如列表

def cal(a=10):
    li=[]
    result=0
    i=1
    while i<=a:
        result+=i
        i+=1
        li.append(result)
    return li
b=cal(5)
print(b)
#运行结果
[1, 3, 6, 10, 15]

函数嵌套调用

定义函数时,可在代码块中调用其他已经定义的函数。

def func1():
    print("this is a function")
def func2():
    func1()
    print("this is another function")
func2()
#运行结果
this is a function
this is another function

应用

写一个函数,找出传入的若干个列表或元组的偶数位对应的元素,并返回新列表:

def func_sum(*args):
    a=len(args)
    li=[]
    for n in range(0,a):
        b=len(args[n])
        for m in range(0,b):
            if m%2==0:
                li.append(args[n][m])
    return li
new_li=func_sum([1,2,3,4,5,],(1,2,3,4,5))
print(new_li)
#运行结果
[1, 3, 5, 1, 3, 5]

写一个函数,检查传入字典的每一个value的长度,如果大于2,那么保留前两个长度的内容,并将截取的字符串修改到原来的字典中,字典中中的value只能是字符串或者列表。

def func_sum(kwargs):
    result={}
    for key,value in kwargs.items():
        if len(value)>2:
            result[key]=value[:2]   #向字典添加数据
            pass
        else:
            result[key]=value
            pass
        pass
    return result
dict_obj={"name":"Mike","age":"20","pro":"art","hobby":"computer games"}
print(func_sum(dict_obj))
#运行结果
{'name': 'Mi', 'age': '20', 'pro': 'ar', 'hobby': 'co'}

局部变量和全局变量

局部变量就是在函数内部定义的变量,作用域仅仅局限在函数的内部,所以不同函数可以定义名字相同的变量,不会相互影响。
作为函数内临时保存数据的存储容器;全局变量作用在整个代码中,包括定义的函数中。

局部变量相当于地头蛇,只在自己函数体内生效,而全局变量在全部局生效,但当局部和全局重复定义时,会优先执行局部变量,即强龙不压地头蛇。

name="Mike"
def func():
    user_name="Alice"
    print(name,user_name)
    pass
func()
#运行结果
Mike Alice

如果在函数体内部对全局变量进行,修改需要使用global函数。

name="Mike"
def func():
    user_name="Alice"
    global name
    name = "Bob"
    print(name,user_name)
    pass
func()
#运行结果
Bob Alice

函数参数引用传值

在Python当中,万物皆对象,在函数调用的时候,实参传递的就是对象的引用;

了解原理后,就可以知道在函数内部的处理是否会影响外部数据的变化。

a=1		#不可变类型
def func(x):
    print("x的内存地址是{}".format(id(x)))
    x=2
    print("x的内存地址是{}".format(id(x)))
    print(x)
    pass
print("a的内存地址是{}".format(id(a)))
func(a)
print(a)
#运行结果
a的内存地址是2199487736112
x的内存地址是2199487736112
x的内存地址是2199487736144
2
1
li=[]		#可变类型
def func(x):
    print("x的内存地址是{}".format(id(x)))
    print("x的内存地址是{}".format(id(x)))
    li.append([1,2,3])
    print("函数内部的li={}".format(li))
    pass
print("li的内存地址是{}".format(id(li)))
func(li)
print("函数外部的li={}".format(li))
#运行结果
li的内存地址是2458644007872
x的内存地址是2458644007872
x的内存地址是2458644007872
函数内部的li=[[1, 2, 3]]
函数外部的li=[[1, 2, 3]]

匿名函数

使用lambda关键字创建函数;没有名字;匿名函数冒号后的表达式只能有一个(是表达式,而不是语句);匿名函数自带return,而这个return的结果就是表达式计算后的结果。

lambda只能是单个表达式,不是一个代码块,labmda的设计就是为了满足简单函数的场景,仅仅能封装有限的逻辑,复杂逻辑无法实现。

lambda 参数1、参数2…参数n:表达式

result=lambda x,y,z:x+y+z
print(result(1,2,3))
#运行结果
6

也可以用于替换双分支if语句:

a,b=2,1
print('suscess' if a>b else 'false')
#运行结果
suscess

直接在匿名函数后面传参:

result=(lambda x,y:x if x>y else y)(16,12)
print(result)
#运行结果
16

递归函数

递归函数即自己调用自己,且必须有一个明确的结束条件;递归函数逻辑简单、定义简单,但也溶质导致栈溢出,内存资源紧张,甚至内存泄漏。

def func(n):
    if n==1:
        return 1
    else:
        return n*func(n-1)
print("5的阶乘是{}".format(func(5)))
#运行结果
5的阶乘是120

案例:树形结构的遍历。

import os       #引入文件操作模块
def find_file(file_path):
    list=os.listdir(file_path)      #得到该路径下所有文件夹
    for file in list:
        full_path=os.path.join(file_path,file)      #获取完整路径
        if os.path.isdir(full_path):        #判断是否为文件夹
            find_file(full_path)    #如果是文件夹,再次去递归
        else:
            print(file_path)
            pass
        pass
    else:
        return
    pass
find_file('D:\INSTALL\知犀\知犀思维导图')
#运行结果
chrome_100_percent.pak
chrome_200_percent.pak
d3dcompiler_47.dll
ffmpeg.dll
...