一.Python函数
1. 定义一个函数
什么是函数
函数是可以重复执行的语句块,可以重复调用
作用
用于封装语句块, 提高代码的重用性。
函数是面向过程编程的最小单位
1.1 def 语句
作用
用来定义( 创建)函数
语法
说明
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
函数名是一个变量,不要轻易对其赋值
函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,但不能轻易对其改变
函数的形参列表如果不需要传入参数,形式参数列表可以为空
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数内容以冒号 : 起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
"""
函数创建
"""
# 无参数
def ttk():
print("mmkdsmcs")
ttk()
# 有参数
def count1(count):
for i in range(count):
print(i)
count1(2)
# return
def qiuhe(x,y):
sum1 = x + y
return sum1
1.2 函数的调用
语法
函数名(实际调用传递参数)
说明
函数调用是一个表达式
如果函数内没有return 语句,函数执行完毕后返回 None 对象
1.3 return 语句
语法
return [表达式]
注: [] 代表 内部的内容可以省略作用
用于函数的内部,结束当前函数的执行,返回到调用此函数的地方,同时返回一个对象的引用关系
说明
return 语句后面的表达式可以省略,省略后相当于 return None
如果函数内部没有 return 语句, 则函数执行完毕后返回None, 相当于在最后一条语句后有一条return None
"""
函数内return执行之后后面的语句都不会执行
"""
re = qiuhe(3,4)
print(re)
2. 函数参数
2.1 函数的调用传参
位置传参
实际参数传递时,实参和形参按位置来依次对应
关键字传参
实际参数传递时,实参和形参 按名称依次对应
注: 位置传参要先于关键字传参
""" 函数参数 实际参数(调用参数) 实参 位置参数 序列实参:使用星号将序列拆分后,与形参进行对应 关键字参数 字典实参 形式参数 默认形参 位置形参 星号元组形参 命名关键字形参 双星号字典形参 """ def dayin(a,b,c): print(a) print(b) print(c) # 位置传参 dayin(1,2,3) # 关键字传参 dayin(a = 1,c = 3,b = 2) # 序列实参 list1 = [2,1,3] dayin(*list1) # 字典实参:使用双星号将字典拆分后,依次与形参对应 dict1 = {"c":3,"b":2,"a":1} dayin(**dict1)
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 函数名(**kwargs): pass
作用
收集多余的关键字传参
注意:
字典形参名最多有一个,字典形参名 一般命名为 kwargs
函数的形参定义方法说明
位置形参,星号元组形参,命名关键字参数,双星号字典形参,缺省参数可以混合使用。
函数的形参定义自左至右的顺序为:位置形参,星号元组形参,命名关键字参数,双星号字典形参
""" 形参 """ # 默认参数:不能放在前面,出现一个之后后面的全部都必须是默认参数 def dayin1(a,b = None,c = 0): print(a) print(b) print(c) dayin1(1) # 星号元组形参:将位置实参合并为一个元组 # 通用写法 *args def dayin2(*args): print(*args) dayin2(4,6,6,5,6) # 双星号字典形参:收集所有的传入参数,打包成字典的形式 # 通用写法 **kwargs,输出时把kwargs当做字典 def dayin3(**kwargs): print(kwargs) dayin3(a=1,b=2,c=3) def dayin4(*args,**kwargs): print(*args) print(kwargs) dayin4(1,3,a = 1,b = 4) # 命名关键字形参:强制,所有的参数都必须用关键字传参 def myfunc4(a, b,*args, c, d): print(a, b, c, d) myfunc4(1, 2, d=4, c=3) # 正确,c,d 必须关键字传参 # myfunc4(1, 2, 3, 4) # 错误
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 [函数的参数列表]: 表达式
作用
创建一个匿名函数对象
lambda
是关键字,表示你正在定义一个匿名函数。同 def 类似,但不提供函数名
[函数的参数列表]
是函数的参数,可以有零个或多个参数,参数之间用逗号分隔。: 表达式
是函数的返回值,通常是一个表达式,匿名函数会计算这个表达式并返回结果。
说明
lambda 表达式 的创建函数只能包含一个表达式
# 匿名函数:也被称为lambda函数,一种简单的、一行的函数,常用于临时需要一个小函数的地方。
chengji = lambda x,y: x*y
print(chengji(2,4))
re = lambda x,y:x+y
print(re(5,7))
5. 变量作用域
5.1 什么是变量作用域
一个变量声明以后,在哪里能够被访问使用,就是这个变量"起作用"的区域:也就是这个变量的作用域
一般来说,变量的作用域,是在函数内部和外部的区域 来体现,因此常常与函数有关
5.2 局部变量和全局变量
局部变量
定义在函数内部的变量称为局部变量(函数的形参也是局部变量)
函数内部的变量只能在函数内部或者函数内部的函数内部访问 ,函数外部不能访问
局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁
全局变量
定义在函数外部,模块内部的变量称为全局变量
全局变量, 所有的函数都可以直接访问(取值,但函数内部不能直接将其赋值改变)
5.3 局部作用域修改全局变量
作用
告诉python 的解释执行器, global 语句声明的一个或多个变量, 这些变量是全局变量
语法
global 变量名1, 变量名2, ....
global 说明
全局变量如果要在函数内部被赋值,则必须经过全局声明 global
默认全局变量在函数内部可以使用,但只能取值,不能赋值
不能先声明为局部变量,再用 global 声明为全局变量,此做法不符合语法规则
函数的形参已经是局部变量,不能用 global 声明为全局变量
"""
变量作用域:LEGB
"""
#全局变量
a = 100
def fun01():
def fun02():
a = 10
print(a)
fun02()
fun01()
# 在函数内部修改全局变量:global
print(a)
def fun03():
global a
a = 1000
fun03()
print(a)
# 外部嵌套作用域
def func01():
a = 10
def func02():
# 内部函数,可以访问外部嵌套变量
# print(a)
# 内部函数,如果修改外部嵌套变量,需要使用nonlocal语句声明
nonlocal a
a = 20
func02()
print(a)
func01()
def fun01(data1,data2):
data1 = 10
data2[0] = 200
a = 20
b = [1,2,3]
fun01(a,b)
print(a,b)
5.4 局部作用域修改外部变量
在函数内部 提前用nonlocal声明 函数内部的某个变量为外部的变量
前提:必须是函数嵌套
说明:
(1)变量的查找顺序还是遵从:LEGB顺序
在 Python 中,LEGB 代表四种作用域的查找顺序:Local、Enclosing、Global 和 Built-in。
(2)局部作用域中若要修改外部函数嵌套作用域中的变量需要使用:nonlocal 语句
格式:nonlocal 变量名
作用:将局部作用域中变量声明为外部函数嵌套作用域中的变量。
LEGB顺序
Local (L):
本地作用域,指当前函数内部的变量。
当你在函数内部定义变量并尝试访问它时,Python 首先会在函数内部查找这个变量。
Enclosing (E):
闭包函数外的函数作用域,指嵌套函数的外部函数中定义的变量。
如果在当前函数内部找不到变量,Python 会查找外层(闭包)函数中的变量。
Global (G):
全局作用域,指模块级别定义的变量。
如果在本地和闭包函数中找不到变量,Python 会查找全局作用域的变量。
Built-in (B):
内建作用域,指 Python 预定义的变量、函数等,如
len
、sum
等。如果在以上三个作用域中都找不到变量,Python 会查找内建作用域。
nonlocal:内部函数,如果修改外部嵌套变量,需要使用nonlocal语句声明
6. 函数的内存分配
1、将函数的代码存储到代码区,函数体中的代码不执行。
2、调用函数时,在内存中开辟空间(栈帧),存储函数内部定义的变量。
3、函数调用后,栈帧立即被释放。
(1) 不可变类型参数有:
数值型(整数,浮点数)
布尔值bool
None 空值
字符串str
元组tuple
(2) 可变类型参数有:
列表 list
字典 dict
集合 set
(3) 传参说明:
不可变类型的数据传参时,函数内部不会改变原数据的值。
可变类型的数据传参时,函数内部可以改变原数据。
7. 函数自调用(递归)
函数直接或间接的调用自身
说明:
递归一定要控制递归的层数,当符合某一条件时要终止递归调用
几乎所有的递归都能用while循环来代替
递归的实现方法:
先假设此函数已经实现
递归优缺点:
优点:
递归可以把问题简单化,让思路更为清晰,代码更简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
"""
递归
计算阶乘
非递归思修
递归思想
"""
def nodigui(n):
result = 1
i = 1
while i<=n:
result *=i
i += 1
return result
print(nodigui(10))
def digui(n):
# 递归边界,返回条件是什么
if n == 1:
return 1
# 调用自己
result = n * digui(n-1)
return result
print(digui(10))
二.API复习
del a 删除变量a
1.字符串 API
str.count(x) 统计字符串x在字符串str中出现的次数
str.split(x) 以x为分隔符将字符串str分割
center(x)将x居中 # center(width,x)
str.join(x) 以x为连接符将str中的每个字符连接起来
str.strip() 执行rstrip()和lstrip()操作,删除字符串两边的空格\t,\r,\n或指定字符。
len(str) 返回字符串的长度
str.replace(old,new,max)将字符串中的某个字符换成新的字符,max为最大次数
str.upper() 将字符串str变成大写
str.lower() 将字符串str变成小写
# str.find(x,beg = 0,end = len(string))检查x是否在str中,如果包含则返回第一个位置的索引值,否则返回-1
# str.index(x,beg = 0,end = len(string))同上,只不过不包含会报错
# max(str) min (str)
2.列表API
list.append(x)将x添加到列表list的末尾
list.count(x) 统计某个元素在列表中出现的次数
list.remove()删除列表的一个元素
list.clear()清空列表
list.pop(i) 将列表中的第i个元素删除,默认为最后一个
len(list)
list.copy()复制列表
list(seq)将元组转换为列表
# max(list) min(list)
# list.extend(seq)在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
# list.index(obj)从列表中找出某个值第一个匹配项的索引位置
# list.insert(index, obj)将对象插入列表
# list.reverse()反向列表中元素
# list.sort( key=None, reverse=False)对原列表进行排序: x.sort(key=lambda a:abs(a-3), reverse=False)
3.字典API
dict.pop(key)删除字典 key所对应的值,返回被删除的值。
dict.clear()
dict.copy()
# dict.items()以列表返回一个视图对象
# dict.keys()返回一个视图对象
# dict.values()返回一个视图对象
# key in dict如果键在字典dict里返回true,否则返回false
# dict.get(key, default=None)返回指定键的值,如果键不在字典中返回 default 设置的默认值
# dict.setdefault(key, default=None)和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
# dict.update(dict2)把字典dict2的键/值对更新到dict里
# popitem()返回并删除字典中的最后一对键和值。
# dict.fromkeys(seq)创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
4.集合API
set.add(x)将x添加到集合set中
set.remove(x)删除集合的一个元素x
set.clear()清空集合
set.copy()
#difference_update()移除集合中的元素,该元素在指定的集合也存在。
#discard()删除集合中指定的元素
# difference() 返回多个集合的差集
# difference_update() 移除集合中的元素,该元素在指定的集合也存在。
# intersection() 返回集合的交集
# intersection_update() 返回集合的交集。
# isdisjoint() 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。
# issubset() 判断指定集合是否为该方法参数集合的子集。
# issuperset() 判断该方法的参数集合是否为指定集合的子集
# pop() 随机移除元素
# symmetric_difference() 返回两个集合中不重复的元素集合。
# symmetric_difference_update() 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。
# union() 返回两个集合的并集
# update() 给集合添加元素
# len() 计算集合元素个数
三.函数总结
函数
定义(创建)
def 函数名(形参):
表达式
形参
1.默认参数:形参处直接赋值,实参有传入则覆盖,无则用默认值
2.命名关键字形参:def 函数名(*或者*args, 命名关键字形参1, 命名关键字形参2, ...):
2.*args列表传参 :可接收不定长的位置参数
3.**kwargs:可接收不定长的关键字参数
调用
实参
1.位置实参:函数名(1,2,3)按顺序
2.关键字实参:函数名(a = 1,b = 2)
3.序列实参:可传入序列依次与形参对应 函数名(*序列名)
4.字典实参:可传入字典依次与形参对应 函数名(**字典名)
返回值
return 可有可无,没有时返回None,执行后函数后面语句不执行
匿名函数
函数名不可调用 简洁
lambda 参数: 表达式 :re = lambda x,y: x+y
re(1,2)
变量 作用域
全局变量:外面没有函数体,全局生效,不能被内部函数直接修改,内部修改要用global声明后
局部变量:函数内部生效,函数执行完毕就释放
查找规则:L(本地)E(嵌套函数)G(全局)B(内置)
nonlocal:嵌套函数内部改外部变量
内存分割:
创建函数是放在代码区,调用时开辟栈帧,函数执行结束后栈帧会释放
不可变类型(不能直接修改):数字,字符串,元组,布尔值
可变类型(可以直接修改,函数内部修改后外部调用时为修改后的): 列表,集合,字典
递归调用
def jiecheng(n):
if n == 1:
return 1
all = n*jiecheng(n-1)
return all
print(jiecheng(10))