Python——函数用法和底层分析(下)
077. 参数的几种类型 Ⅰ
位置参数
函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。按位置传递的参数,称为:“位置参数”。
默认值参数
我们可以为某些参数设置默认值,这样这些参数在传递时就是可选的,称为“默认值参数”。默认值参数放到位置参数后面。
命名参数
我们也可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。
# 参数的类型
# 位置参数和命名参数
def test01(a,b,c,d):
print("{0}-{1}-{2}-{3}".format(a,b,c,d))
test01(10,20,30,40) # 位置参数
# test01(10,20) # 参数个数不匹配
test01(d=90,c=40,a=20,b=50) # 命名参数
# 默认值参数
def test02(a,b,c=5,d=4): # 默认值参数,必须位于其他参数后面
print("{0}-{1}-{2}-{3}".format(a, b, c, d))
test02(2,3) # 没有给c,d赋值时,c,d取默认值参数
078. 参数的几种类型 Ⅱ
可变参数
可变参数指的是“可变数量的参数”。分两种情况:
- *param(一个星号) ,将多个参数收集到一个 “元组” 对象中。
- **param(两个星号) ,将多个参数收集到一个 “字典” 对象中。
强制命名参数
在带星号的“可变参数”后面增加新的参数,必须在调用时“强制命名参数”。
080. lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数。 lambda函数是一种简单的、在同一行中定义函数的方法。lambda函数实际生成了一个函数对象。
lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。
lambda表达式的基本语法如下:
arg1/arg2/arg3为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。
# lambda表达式和匿名函数
f = lambda a,b,c:a+b+c
print(f(5,6,7))
def test01(a,b,c): # 同上
return a+b+c
g = [lambda a:a*2,lambda b:b+8]
print(g[0](2),g[1](5))
h = [test01,test01] # 函数也是对象
print(h[0](3,4,5))
080. eval()函数
- 功能:将字符str当成有效的表达式来求值并返回计算结果。
- 语法:
eval(source[, globals[, locals]]) -> value - 参数:
source:一个Python表达式或函数compile()返回的代码对象。
globals:可选。必须是dictionary。
locals:可选。任意映射对象。
# eval()函数
s = "print('abc')" # s也可是文件
eval(s) # s从客户端发来的
a = 10
b = 20
c = eval("a+b")
print(c)
dict1 = dict(a=40,b=50)
d = eval("a+b",dict1) # 如果没加dict1,则计算的a和b是10和20
print(d)
081. 递归函数
递归函数指的是:自己调用自己的函数,在函数体内部直接或间接地自己调用自己。
每个递归函数必须包含两个部分:
- 终止条件
表示递归什么时候结束。一般用于返回值,不再调用自己。 - 递归步骤
把第n步的值和第n-1步相关联。
# 递归函数
def test01(n):
print("test01:",n)
if n==0:
print("over")
else:
test01(n-1)
print("test01***",n)
test01(4)
运行结果:
082. 递归函数_阶乘计算
# 使用递归函数,计算阶乘
def factorial(n):
if n==1:
return 1
else:
return n*factorial(n-1)
result = factorial(5)
print(result)
083. 嵌套函数(内部函数)
嵌套函数:在函数内部定义的函数。
一般在什么情况下使用嵌套函数?
- 封装 - 数据隐藏
外部无法访问“嵌套函数” - 贯彻DRY(Don’t Repeat Yourself)原则
嵌套函数,可以让我们在函数内部避免重复代码。 - 闭包
# 嵌套函数(内部函数)
def outer():
print("outer running")
def inter01():
print("inter01 running")
inter01() # 嵌套函数,仅能在outer函数内调用
outer()
# 打印中英文名字
# 方法一 定义两个方法
def printChineseName(name,familyName):
print("{0}{1}".format(familyName,name))
def printEnglishName(name,familyName):
print("{0}{1}".format(name,familyName))
# 方法二 嵌套函数
def printName(isChinese,name,familyName):
def inter_print(a,b):
print("{0}{1}".format(a,b))
if isChinese:
inter_print(familyName,name)
else:
inter_print(name,familyName)
printName(True,"三","张")
printName(False,"Jonny","Green")
084. nonlocal关键字
- nonlocal:用来声明外层的局部变量
- global:用来声明全局变量
# nonlocal、global关键字的用法
a = 100
def outer():
b = 10
def inter():
nonlocal b # 声明外部函数的局部变量b
print("inter b:",b) # 可直接调用外部变量
b = 20 # 声明后可修改b的值
global a # 声明全局变量a
a = 200 # 声明后可修改a的值
inter()
print("outer b:",b) # b的值为20,此时b的值已被修改
outer()
print("a:",a) # a的值为200,此时a的值已被修改
085. LEGB规则
Pthon在查找“名称”时,是按照LEGB规则查找的:
Local:指的就是函数或者类的方法内部
Enclosed:指的是嵌套函数(一个函数包裹另一个函数,闭包)
Global:指的是模块中的全局变量
Built in :指的是Python为自己保留的特殊名称
如果某个name映射在 局部(local)命名空间 中没有找到,接下来就会在 闭包作用域(enclosed) 进行搜索,如果闭包作用域也没有找到,Python就会到 全局(global)命名空间 中进行查找,最后会在 内建(built-in)命名空间 搜索(如果一个名称在所有命名空间中都没有找到,就会产生一个 NameError )。
# LEGB规则 Local → Enclosed → Global → Built in
# str = "global str" # 查找“名称”时,第3个查找(Global )
def outer():
# str = "outer" # 查找“名称”时,第2个查找(Enclosed)
def inner():
# str = "inner" # 查找“名称”时,第1个查找(Local)
print(str)
inner()
outer()
运行结果:
上图为第4个查找(Built in),如果还是找不到,则产生NameError。