函数的用法和底层分析
一、函数的概念
1. 一个程序由一个个任务组成;函数就是代表一个任务或者一个功能。
python的函数类型
二、函数的定义和调用
三、实参和形参
def printMax(a,b):
""""实现两个数的比较,并返回最大值"""
if a>b:
print(a,"较大值")
else:
print(b,"较大值")
printMax(10,20)
四、文档字符串(函数的注释)
我们调用 help(函数名.__doc__)可以打印输出函数的文档字符串。执行结果如下:Help on function print_star in module __main__:print_star(n)根据传入的 n,打印多个星号
五、返回值
六、函数也是对象
七、全局变量和局部变量
#全局变量和局部变量的测试
a=100 # 全局变量
def f1():
global a #改变全局变量a的
a = 300
print(a)
f1()
print(a)
执行结果:
300
300
# 【操作】 输出局部变量和全局变量
a = 100
def f1(a,b,c):
print(a,b,c)
print(locals()) #打印局部变量
print("*"*20)
print(globals()) #打印全局变量
f1(1,2,3)
执行结果:
1 2 3
{'a': 1, 'b': 2, 'c': 3}
********************
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F073F37C70>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:\\PyCharm2021.3.3\\pythonProjects\\pythonProject\\pythonjichulianxi\\globals or local variables.py', '__cached__': None, 'a': 100, 'f1': <function f1 at 0x000001F0743CBB50>}
八、参数的传递
1、传递可变参数
2、传递不可变参数
3、浅拷贝和深拷贝
#测试浅拷贝和深拷贝
import copy
def testCopy():
"""测试浅拷贝"""
a=[10,20,[5,6]]
b=copy.copy(a)
print("a",a)
print("b",b)
b.append(30)
b[2].append(7)
print("浅拷贝")
print("a",a)
print("b",b)
def testDeepCopy():
"""测试深拷贝"""
a = [10, 20, [5, 6]]
b = copy.deepcopy(a)
print("a", a)
print("b", b)
b.append(30)
b[2].append(7)
print("深拷贝")
print("a", a)
print("b", b)
testCopy()
print("*************")
testDeepCopy()
>>> 运行结果 <<<
a [10, 20, [5, 6]]
b [10, 20, [5, 6]]
浅拷贝
a [10, 20, [5, 6, 7]]
b [10, 20, [5, 6, 7], 30]
*************
a [10, 20, [5, 6]]
b [10, 20, [5, 6]]
深拷贝
a [10, 20, [5, 6]]
b [10, 20, [5, 6, 7], 30]
九、参数的几种类型
1、位置参数
# 位置参数
def f1(a,b,c):
print(a,b,c)
f1(1,2,3)
f1(1,2) #报错,位置不匹配
2、默认值参数
def f2(a,b,c=10,d=20): #默认值参数必须位于普通参数后面
print(a,b,c,d)
f2(2,8)
f2(2,8,5) #依次赋值
f2(2,3,4,5)
>>>运行结果<<<
2 8 10 20
2 8 5 20
2 3 4 5
3、命名参数
# 命名参数
def f3(a,b,c):
print(a,b,c)
f3(1,2,3) #位置参宿
f3(c=10,b=20,a=30) #命名参数 按照定义时顺序输出
>>>运行结果<<<
1 2 3
30 20 10
4、可变参数
#可变参数
def f4(a,b,*c): # 元组
print(a,b,c)
f4(1,2,3,4,5,6)
def f5(a,b,**c): #字典
print(a,b,c)
f5(7,8,name="LQQ",age=24)
5、强制命名参数
# 强制命名参数
def f6(*a,b,c):
print(a,b,c)
f6(2,3,4) #报错,所有值都赋值给a,bc赋值失败
f6(2,b=3,c=4) #可变参数后需要使用强制命名参数赋值
>>>运行结果<<<
(2,) 3 4
6、lambda表达式和匿名函数
#lambda 表达式和匿名函数
f1=lambda a,b,c,d:a*b*c*d
print(f1(1,2,3,4))
def test01(a,b,c,d):
print("********")
return a*b*c*d
g=[lambda a:a*2,lambda b:b*3]
print(g[0](2),g[1](5))
h=[test01,test01]
print(h[0](2,2,4,5))
>>>运行结果<<<
24
4 15
********
80
十、递归函数
递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己。递归类似于大家中学数学学习过的“数学归纳法”。
每个递归函数必须包含两个部分:
1. 终止条件:表示递归什么时候结束。一般用于返回值,不再调用自己。
2. 递归步骤:把第 n 步的值和第 n-1 步相关联。
递归函数由于会创建大量的函数对象、过量的消耗内存和运算能力。在处理大量数据时,谨慎使用。
#测试递归函数的基本原理
def test01(n):
print("test01",n)
if n==0:
print("over")
else:
test01(n-1)
print("*******",n)
test01(4)
>>>运行结果<<<
test01 4
test01 3
test01 2
test01 1
test01 0
over
******* 0
******* 1
******* 2
******* 3
******* 4 #进栈时,先进后出,后进先出依次执行结束后出栈
#用递归函数做阶乘
def factorial(n):
if n==1:
return 1
else:
return n*factorial(n-1)
for i in range(1,6):
print(i,"!=",factorial(i))
>>>运行结果<<<
1 != 1
2 != 2
3 != 6
4 != 24
5 != 120
十一、嵌套函数
一般在什么情况下使用嵌套函数?
1. 封装,数据隐藏——外部无法访问“嵌套函数”。
2. 贯彻 DRY(Don’t Repeat Yourself) 原则,嵌套函数,可以让我们在函数内部避免重复代码。
3. 闭包
#嵌套函数格式
def outer():
print("this is outer function:")
def inner():
print("this is inner function")
inner()
outer()
十二、nonlocal关键字 —— 调用外部变量
nonlocal 用来声明外层的局部变量。
global用来声明全局变量。
#嵌套函数
a=100
def outer():
b=10
def inner():
nonlocal b
print("inner b",b)
b=20
inner()
print("outer,b",b)
outer()
>>>运行结果<<<
inner b 10
outer,b 20
十三、LEGB规则——从里往外检索
Python 在查找“名称”时按照 LEGB 规则查找的:Local-->Enclosed-->Global-->Built in
Local指的就是函数或者类的方法内部,Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包) ,Global 指的是模块中的全局变量 ,Built in 指的是 Python 为自己保留的特殊名称。
如果某个 name 映射在局部(local)命名空间中没有找到,接下来就会在闭包作用域(enclosed)进行搜索,如果闭包作用域也没有找到,Python 就会到全局(global)命名空间中进行查找,最后会在内建(built-in)命名空间搜索 (如果一个名称在所有命名空间 中都没有找到,就会产生一个NameError)。