一 基本声明
函数声明语法
def 函数名(参数列表): ''' # 函数文档 params: return: ''' # 实现特定功能的多行代码 [return [返回值]]
函数调用语法
函数名()
查看说明文档
方式一: print(函数名.__doc__) 方式二: help(函数名)
二 函数参数
函数参数 | 实例 |
形参和实参 |
def add(x, y): # 声明的参数称之为形式参数,简称形参 |
位置参数 |
def add(x,y): # x,y是形参,用来接收实参 print(x+y) add(2,3) # 2,3 是实际参数,分别传递给形参x,y |
默认参数 | def print_stu_info(name,age,gender="male"):
print("学员姓名:",name) print_stu_info("张三",23) #有默认值的参数必须位于所有没默认值参数的后面,否则报错! |
关键字参数 |
def print_stu_info(name,age,height,weight,job): print("学员姓名:",name) print_stu_info("张三",height="180cm",weight="90kg",job="销售",age=23) #使用位置参数和关键字参数混合传参的方式。但需要注意,混合传参时关键字参数必须位于所有的位置参数之后。 |
不定长参数 |
def print_stu_info(name, age=18, *args, **kwargs): print_stu_info("小红", 20, "China", "Beijing", height="188cm", weight="60kg") #虽然有了不定长实参,但是如果函数声明时,使用的是位置形参,则不定长实参的数量一定要和位置形参的数量对应!! |
注:
1 不定长参数
(1)在工作中,有时候就会有些函数,就要接收个数不确定的参数。这时候,都可以使用不定长参数来完成。
不定长参数有2种写法:
1. 在形参的位置参数左边使用*表示,接收0~多个位置实参,这种情况下,*号左边的形参,在函数内部就是一个元组。在函数定义中使用*args传递非命名键值可变长参数列表
2. 在形参的位置参数左边使用**表示,接收0~多个关键字参数,这种情况下,**号左边的形参,在函数内部就是一个字典。在函数定义中使用**kwargs传递键值可变长参数列表
(2)有了不定长形参以后,也可以在形参中继续使用位置参数和默认参数
形参的书写顺序:位置形参 > 默认形参 > 元组不定长形参 > 字典不定长形参
(3)可以使用*号把元组,列表,打散成位置实参,也可以使用**号把字典打散成关键字实参
""" 调用函数时,我们如果参数较多,可以使用不定长实参: 可以使用*号把元组,列表,打散成位置实参 也可以使用**号把字典打散成关键字实参 """ student_list = [ {"name":"小名", "age": 17, "sex": True, "mobile": "1331234567"}, {"name":"小白", "age": 27, "sex": False, "mobile": "1361234567"}, ] def func3(name, age, mobile, sex=False): """打印学生信息""" print(f"name={name}") print(f"age={age}") print(f"sex={sex}") print(f"mobile={mobile}") # # 打印小白的信息 # func3(student_list[1]["name"], student_list[1]["age"], student_list[1]["mobile"]) # # # 上一行代码,太长了,针对上面的代码,其实就是把字典中所有的数据传递给函数内部 # stu = student_list[1] # func3(name=stu["name"], age=stu["age"], mobile=stu["mobile"]) # 使用**打散,可以让上面代码可以缩写成一句 # stu = student_list[1] # func3(**stu) # 就是上面代码的简写 func3(name=stu["name"], age=stu["age"], mobile=stu["mobile"])
三 函数返回值
我们希望把函数内部产生的一些数据或者结构返回给调用处,那么可以使用return关键字返回值。如果没有return语句或者return后没有具体值,都默认返回None。
特殊的常量 None(N 必须大写)。和 False 不同,它不表示 0,也不表示空字符串,而表示没有值,也就是空值
函数的结果,可以没有,也可以有一个或者多个,但是return只能执行一次,且执行到了return,则表示当前函数已经执行结束了,后续代码将不会被执行
def func2(x, y):
ret1 = x + y
ret2 = x - y
return ret1, ret2 # 可以通过组包的方式,把函数中数据,变量,返回给外界调用处。
a, b = func2(1, 2). # 3 -1 #使用=号在函数调用的左边声明变量来接收函数的返回值
注:在使用python的内置函数或者其他人声明的函数,要知道它是否有结果,可以通过pycharm提供的查看函数的说明文档来了解。
在函数说明文档中,如果没有发现 -> 或者 出现 ->None 的都表示当前函数没有返回结果,没有返回结果就不需要在调用函数时使用=号和变量接受结果了。
四 函数作用域
1 函数嵌套:函数内部声明一些函数,这些函数,在函数的外界无法使用。
2 作用域:变量的有效范围。变量在python代码执行过程中,该变量的使用范围和生命周期
3 LEGB:根据变量声明的位置和使用的位置,分函数外和函数内,文件外和文件内,有以下4种不同的作用域级别
因为作用域的问题,所以按不同作用域可以把变量划分为2种:局部变量与全局变量。
-
局部变量,函数内部声明的变量。默认情况下,只有在函数运行时局部变量才会出现在内存中,当函数执行结束,内存中的局部变量就会被销毁,所以局部变量无法被当前函数以外的地方使用。
-
实例:
函数内部的局部变量如果与函数外部的全局变量的名字一样,则优先使用局部变量 """函数在有需要的情况下,也可以声明全局变量或者在同名情况下设置优先调用全局变量""" num = 10 # 全局变量,所在的作用域是全局作用域 def func1(): # 通过global关键字,可以设置函数内部的1个或多个变量为全局变量 # global 变量1,变量2,..... global num # 通过global关键字,让当前函数使用变量num时,调用全局作用域下的num num = 20 func1() print(num) # 20 """ 在嵌套函数的时候,就会存在嵌套作用域 """ """ 情况1:在函数内部,如果没有对应的变量名,则函数内部会往函数外部,查找对应的变量,当找到以后,直接调用。找不到再报错。 """ # num = 10 # 函数外,属于全局作用域 # def func1(): # print(f"func1, num={num}") #func1, num=10 # 嵌套函数的外部,属于func2的嵌套作用域 # def func2(): # print(f"func2, num={num}") # func2, num=10 # 函数内部,属于func2的局部作用域 # func2() # func1() # print(f"函数外, num={num}") # 函数外, num=10 """ 情况2:当函数内部存在变量赋值语句,则函数内部如果没有global或者nolocal关键字,则表示在函数内部声明一个局部变量。 该变量,可以被当前作用域下的后续代码调用,也可以被嵌套函数内部(子作用域)调用。 """ # num = 10 # 函数外,属于全局作用域 # def func1(): # num = 20 # 此处,是赋值语句,因为当前函数没有出现global或nolocal关键字 # print(f"func1, num={num}") # func1, num=20 # 嵌套函数的外部,属于num的本地作用域 # def func2(): # print(f"func2, num={num}") # func2, num=20 # func2是func1的子作用域,func1是func2的父作用域 # func2() # func1() # print(f"函数外, num={num}") # 函数外, num=10 总结: 在函数嵌套过程中,每次嵌套都会产生一个新的嵌套作用域,包含的作用域就产生了父作用域和子作用域的情况。 子作用域下的局部变量无法被父作用域使用。 子作用域要调用父作用域的变量,则可以通过nolocal关键字调用 子作用域要调用全局作用域的变量,则可以通过global关键字来调用 # a = 10 # b = 20 # c = 30 # def func1(): # c = 40 # d = 50 # e = 100 # print(f"func1,a={a}") # func1,a=10 # def func2(): # global c # 获取顶级作用域下的c # print(f"func2,b={b}") # func2,b=20 # print(f"func2,c={c}") # func2,c=30,global直接让变量指向到了函数外全局作用域的全局变量,跳过了父作用域 # func2() # def func3(): # # nolocal表示接下来,进行赋值操作的变量不是在当前作用域下创建局部变量,而是调用来自父级作用域下的变量 # # nonlocal 变量1,变量2,.... # nonlocal d # d = 60 # 赋值语句 # print(f"func3,b={b}") # func3,b=20 # print(f"func3,c={c}") # func3,c=40 # print(f"func3,d={d}") # func3,d=60 # e = 200 # 此处的赋值语句,因为在函数func3中没有表示当前e是属于父作用域或全局作用域的,因此这个就是声明局部变量 # print(f"func3,e={e}") # func3,e=200 # func3() # print(f"func1, d={d}") # func1, d=60 # func3中的修改d的时候设置nolocal,所以d就是func3的父作用域func1的变量d了 # print(f"func1, e={e}") # func1, e=100,func3中的局部改了,对于外界是不影响的。 # func1() """ 内置作用域,其实就是文件模块以外,由python解释器内置的变量命名空间。 在任意位置执行访问都可以得到内置作用域的变量,但是当全局作用域下或局部作用域下,出现同名赋值,则相当于创建一个当前作用域的变量。 但是其他python文件中,依然可使用内置作用域下的变量。 """ # print(max) # <built-in function max> # max = 10 # print(max) # 10
五 匿名函数
定义:也叫 lambda 表达式。
语法格式:
1 格式1: 2 变量 = lambda 参数列表: 返回结果 3 格式2: 4 lambda 参数列表: 返回结果 5 6 """ 7 # 格式1: 8 # add = lambda x,y: x + y 9 # ret = add(10,20) 10 # print(ret) 11 12 # 格式2: 13 # ret = (lambda x, y: x + y)(10,20) # 声明匿名函数的同时,直接调用了 14 # print(ret)
实例:
"""lambda在工作中也是比较常用,一般有如下集中情况:""" """1. 列表排序""" # data1 = [11, 2, 20, 21, 3, "5", "10"] # # 方式1: # # key参数可以指定列表在排序时,前后两个成员比较大小时的代码段 # # def func(a): # # return int(a) # # data1.sort(key=func) # # 方式2:上面的代码就可以使用lambda简写了 # data1.sort(key=lambda x: int(x)) # print(data1) # [2, 3, '5', '10', 11, 20, 21] """ 声明一个函数,就需要在内存中保存这段代码,肯定会需要额外的内存空间。 声明一个匿名函数,则传入到函数内部时,才会在存在出现,在函数执行以后,这个匿名函数就会被内存空间回收(销毁了,删除了) """ """2. 字典排序""" # data2 = {"name": "小名", "age": 18, "money": 30.00, "mobile": "13312345678"} # data3 = [ # {"name":"商品1", "price": 30.00}, # {"name":"商品2", "price": 55.00}, # {"name":"商品3", "price": 19.00}, # {"name":"商品4", "price": 9.90}, # ] # # def func(x): # # return x["price"] #取key=price的value值 # data3.sort(key=lambda x: x["price"]) # 从小到大 # data3.sort(key=lambda x: x["price"], reverse=True) # 从大到小 # print(data3) """3. 作为参数传递到另一个函数中使用""" # 四则运算(加减乘除)的计算机 def calc(x, y, o): """计算器,完成2个数字的运算""" print("记录操作过程。。。。") ret = o(x, y) print("记录操作结果。。。。") return ret ret = calc(10, 20, lambda x, y: x + y) #等同于(lambda x, y: x + y)(10,20) #lambda:匿名函数,x,y:形参,x+y:函数里的表达式,(10,20):实参
print(ret)
六 函数名的使用
整数、浮点数、字符串、列表、字典、元组、函数、类本身、类型本身以及模块等都是对象。
因为都是对象,所以 Python 中的函数才和整数、字符串、列表、字典和元组等对象的地位是平等的,成为了“一等公民”。python中函数与其他数据类型一样同属于一等公民(first-class elements,也叫一等对象)。
“一等公民”是指代满足下述条件的程序实体:
1、可赋值给变量,让变量代表它运行。 变量=xxx
2、可作为函数的参数。 函数名(xxx)
3、可作为函数结果返回。 return xxx
4、可包含在数据结构中,例如可以包含在列表等数据类型中作为成员存在。 {"a":xxx}
# 也可以作为复合数据类型的成员值存在 data = { "+": lambda x, y: x + y, "-": lambda x, y: x - y, "*": lambda x, y: x * y, "/": lambda x, y: x / y, } print(data["+"]) # <function <lambda> at 0x000001FECE5DA670> print(data["+"](10, 20)) # 30
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY