1.定义一个函数
函数是可以重复执行的语句块,可以重复调用
作用
用于封装语句块, 提高代码的重用性。
函数是面向过程编程的最小单位
1.1 def 语句
用来定义( 创建)函数
语法
def 函数名(形式参数列表): 语句块
说明
-
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
-
函数名是一个变量,不要轻易对其赋值
-
函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外
部的变量,但不能轻易对其改变
-
函数的形参列表如果不需要传入参数,形式参数列表可以为空
-
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
-
函数内容以冒号 : 起始,并且缩进。
-
return [表达式]结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回None。
1.2 函数的调用
语法
函数名(实际调用传递参数)
说明
函数调用是一个表达式
如果函数内没有return 语句,函数执行完毕后返回 None 对象
1.3 return 语句
语法
return [表达式] 注: [] 代表 内部的内容可以省略
作用
用于函数的内部,结束当前函数的执行,返回到调用此函数的地方,同时返回一个对象的引用关系
说明
-
return 语句后面的表达式可以省略,省略后相当于 return None
-
如果函数内部没有 return 语句, 则函数执行完毕后返回None, 相当于在最后一条语句后有一条
return None
2. 函数参数
2.1 函数的调用传参
位置传参
实际参数传递时,实参和形参按位置来依次对应
关键字传参
实际参数传递时,实参和形参 按名称依次对应
注**:** 位置传参要先于关键字传参
2.2 函数的形式参数定义方法
函数的缺省参数(默认参数)
语法
def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ... ): 语句块
说明
缺省参数即默认实参,必须自右向左依次存在(即,如果一个参数有缺省参数,则其右侧的所有参数都必须
有缺省参数)
形参的定义
位置形参
星号元组形参(*args)
命名关键字形参
双星号字典形参(**kwargs)
1)位置形参
语法:
def 函数名(形参名1, 形参名2, ...): pass
2)星号元组形参
语法
def 函数名(*元组形参名): pass 作用 收集多余的位置实参 元组形参名一般命名为args
3)命名关键字形参
语法
def 函数名(*, 命名关键字形参1, 命名关键字形参2, ...): pass # 或者 def 函数名(*args, 命名关键字形参1, 命名关键字形参2, ...): pass 作用 强制,所有的参数都必须用关键字传参
4)双星号字典形参
语法
def 函数名(**字典形参名): pass 作用 收集多余的关键字传参 字典形参名最多有一个, 字典形参名 一般命名为 kwargs
函数的形参定义方法说明
位置形参,星号元组形参,命名关键字参数,双星号字典形参,缺省参数可以混合使用。
函数的形参定义自左至右的顺序为:位置形参,星号元组形参,命名关键字参数,双星号字典形参
2.3 可变不可变
可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向
它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有
动,只是其内部的一部分值被修改了。
python 函数的参数传递:
不可变类型:值传递: 如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本
身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
可变类型:引用传递: 如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la
也会受影响
python 中一切都是对象(后面会讲),严格意义我们不能说值传递还是引用传递,我们应该说传不可变对
象和传可变对象。
3. 返回值
函数可以使用 return 语句来返回一个或多个值。
如果没有明确的 return 语句,函数将默认返回 None 。
4. 匿名函数
在Python中,匿名函数通常使用 lambda 关键字来创建。匿名函数也被称为lambda函数,它是一种简单
的、一行的函数,常用于临时需要一个小函数的地方。匿名函数的语法如下:
语法
lambda [函数的参数列表]: 表达式
作用
1.创建一个匿名函数对象 2.lambda 是关键字,表示你正在定义一个匿名函数。 3.同 def 类似,但不提供函数名 4.[函数的参数列表] 是函数的参数,可以有零个或多个参数,参数之间用逗号分隔。 5.表达式 是函数的返回值,通常是一个表达式,匿名函数会计算这个表达式并返回结果。
说明
lambda 表达式 的创建函数只能包含一个表达式
5. 变量作用域
一个变量声明以后,在哪里能够被访问使用,就是这个变量"起作用"的区域:也就是这个变量的作用域
一般来说,变量的作用域,是在函数内部和外部的区域 来体现,因此常常与函数有关
5.1 局部变量和全局变量
局部变量 1.定义在函数内部的变量称为局部变量(函数的形参也是局部变量) 2.函数内部的变量只能在函数内部或者函数内部的函数内部访问 ,函数外部不能访问 3.局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁 全局变量 1.定义在函数外部,模块内部的变量称为全局变量 2.全局变量, 所有的函数都可以直接访问(取值,但函数内部不能直接将其赋值改变)
5.2 局部作用域修改全局变量
告诉python 的解释执行器, global 语句声明的一个或多个变量, 这些变量是全局变量
global 变量名1, 变量名2, .... global 说明 全局变量如果要在函数内部被赋值,则必须经过全局声明 global 默认全局变量在函数内部可以使用,但只能取值,不能赋值 不能先声明为局部变量,再用 global 声明为全局变量,此做法不符合语法规则 函数的形参已经是局部变量,不能用 global 声明为全局变量
# 如何用一个变量来记录一个函数调用的次数 count = 0 def hello(name): global count # 声明 global 是全局变量 print('hello', name) count += 1 # 等同于 count = count + 1 hello('小张') hello('小李') hello('小魏') print('您共调用hello函数', count, '次') # 3 次
5.3 局部作用域修改外部变量
在函数内部 提前用nonlocal声明 函数内部的某个变量为外部的变量
前提:必须是函数嵌套
说明:
(1)变量的查找顺序还是遵从:LEGB顺序
在 Python 中,LEGB 代表四种作用域的查找顺序:Local、Enclosing、Global 和 Built-in。
(2)局部作用域中若要修改外部函数嵌套作用域中的变量需要使用:nonlocal 语句
格式:nonlocal 变量名
作用:将局部作用域中变量声明为外部函数嵌套作用域中的变量。
LEGB顺序
-
Local (局部):当前函数或类的局部命名空间。包括函数的参数和局部定义的变量。
-
Enclosing function locals (闭包函数的局部):如果当前函数是在另一个函数体内部定义的,那么外部函数的命名空间也包含在内。
-
Global (全局):模块级别的命名空间,即当前模块的顶层定义。一个模块的全局命名空间是对其他模块不可见的。
-
Built-in (内置):包含内置函数名字的命名空间。这些是 Python 解释器内置的名字,如
len()
、str()
等。
在 Python 中,当引用一个变量(名称)时,解释器会按照 LEGB 的顺序搜索变量:
-
首先搜索局部命名空间(Local)。
-
如果没有找到,搜索闭包函数的局部命名空间(Enclosing)。
-
如果还没有找到,搜索全局命名空间(Global)。
-
最后搜索内置命名空间(Built-in)。
6. 函数的内存分配
1、将函数的代码存储到代码区,函数体中的代码不执行。
2、调用函数时,在内存中开辟空间(栈帧),存储函数内部定义的变量。
3、函数调用后,栈帧立即被释放。
(1) 不可变类型参数有: 数值型(整数,浮点数) 布尔值bool None 空值 字符串str 元组tuple (2) 可变类型参数有: 列表 list 字典 dict 集合 set (3) 传参说明: 不可变类型的数据传参时,函数内部不会改变原数据的值。 可变类型的数据传参时,函数内部可以改变原数据。
7. 函数自调用(递归)
说明: 递归一定要控制递归的层数,当符合某一条件时要终止递归调用 几乎所有的递归都能用while循环来代替 递归的实现方法: 先假设此函数已经实现 递归优缺点: 优点: 递归可以把问题简单化,让思路更为清晰,代码更简洁 缺点: 递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果