函数
函数的定义和调用
定义函数需要用 def 关键字实现,具体的语法格式如下:
def 函数名(形参列表):
//由零条到多条可执行语句组成的代码块
[return [返回值]]
函数的调用直接写出函数名加小括号
def hm():
print('laohu真帅')
print(hm())#laohu真帅
函数的参数
函数参数的作用是传递数据给函数,令其对接收的数据做具体的操作处理。
参数从调用角度来看,分为形式参数与实际参数
-
形式参数:在定义函数时,函数名后面括号中的参数就是形式参数
-
实际参数:在调用函数时,函数名后面括号中的参数称为实际参数,也就是函数的调用者给函数的参数。
def hm(name):
print(name+'真帅')
#name为形参
print(hm('laohu'))#laohu真帅
#laohu是实参
实参和形参的区别,就如同剧本选主角,剧本中的角色相当于形参,而演角色的演员就相当于实参。
函数文档
使用函数文档帮助更好理解函数作用
在函数开头写下字符串,其不被打印出来,但作为函数的一部分保存起来了。称作函数的文档字符串
函数的文档字符串通过__doc__获取
用help()查看文档
def jiafa(a,b):
"返回加法"
print(a,b)
print(help(jiafa))#jiafa(a, b)
#返回加法
print(jiafa.__doc__)#返回加法
关键字参数及用法
- 位置参数有时也称必备参数,指的是必须按照正确的顺序将实际参数传到函数中,换句话说,调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致。否者会出现错误
- 关键字参数是指使用形式参数的名字来确定输入的参数值。通过此方式指定函数实参时,不再需要与形参的位置完全一致,只要将参数名写正确即可。
def shuai(a,b):
return(a+"比"+b+"帅")
print(shuai('小方','小明'))#小方比小明帅
print(shuai(b='小方',a='小明'))#小明比小方帅
默认参数设置
默认参数是指在定义函数时,直接给形式参数指定一个默认值
def shuai(a='',b=''):
return a+"比"+b+"帅"
print(shuai('小方','小明'))#小方比小明帅
print(shuai(b='小方',a='小明'))#小明比小方帅
``
return函数返回值
def 语句创建函数时,可以用 return 语句指定应该返回的值,该返回值可以是任意类型。需要注意的是,return 语句在同一函数中可以出现多次,但只要有一个得到执行,就会直接结束函数的执行。
变量作用域(全局变量和局部变量)
在程序中定义一个变量时,这个变量是有作用范围的,变量的作用范围被称为它的作用域。根据定义变量的位置(有效范围),可以将变量分为局部变量和全局变量。
- 局部变量
局部变量是指在函数内部定义并使用的变量,它只在函数内部有效。
pyth运行函数时候,利用栈储存,当函数执行完成后,这块内存空间就被释放了,这些局部变量也就失效了。因此离开函数之后就不能再访问局部变量了,否则解释器会抛出 NameError 错误。
def hm():
a='hu 真帅'
return a
print(hm())#hu 真帅
print(a)#NameError: name 'a' is not defined
- 全局变量
全局变量指的是能作用于函数内外的变量,即全局变量既可以在各个函数的外部使用,也可以在各函数内部使用
定义全局变量的方式有以下 2 种:
- 在函数体外定义的变量,一定是全局变量
a='hu 真帅'
def hm():
return a
print(hm())#hu 真帅
print(a)#hu 真帅
- 在函数体内定义全局变量。即使用 global 关键字对变量进行修饰后,该变量就会变为全局变量。
def hm():
global a
a='hu 真帅'
return a
print(hm())#hu 真帅
print(a)#hu 真帅
- 获取指定作用域范围中的变量
在函数的局部范围内还是在全局范围内,都可能存在多个变量,每个变量“持有”该变量的值。从这个角度来看,不管是局部范围还是全局范围,这些变量和它们的值就像一个“看不见”的字典,其中变量名就是字典的 key,变量值就是字典的 value。实际上,Python 提供了如下三个工具函数来获取指定范围内的“变量字典” - globals():该函数返回全局范围内所有变量组成的“变量字典”。
- locals():该函数返回当前局部范围内所有变量组成的“变量字典”。
- vars(object):获取在指定对象范围内所有变量组成的“变量字典”。如果不传入object 参数,vars() 和 locals()的作用完全相同。
def hm():
a=20
b=10
print(a,b)#20 10
print(locals())#{'a': 20, 'b': 10}
print(locals()['a'])#20
locals()['a']=5#通过locals函数局部范围的“变量数组”改变a变量的值
print(locals()['a'])#20,值不改变
globals()['x']=15
c=30
d=25
print(c)#30
globals()['c']=15#通过全局变量的“变量数组”对x全局变量赋值
print(c)#15
locals()['c'] = 99#在全局范围内使用locals函数对x全局变量赋值
print(c) # 输出99
print(globals())#{... 'c': 30, 'd': 25}
print(locals())#{... 'c': 30, 'd': 25}
hm()
- 不定长参数
需要一个函数能处理比当初声明时更多的参数,这些参数叫做不定长参数。
基本语法:
def functionname([formal_args,] *var_args_tuple ):
“函数_文档字符串”
function_suite
return [expression]
加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
def hm( a, *vartuple ):
print(a)#10
print("vartuple中有%d个参数"%len(vartuple))#vartuple中有2个参数
print(vartuple[0])#20
return vartuple#(20, 30)
#vartuple以元组形式返回
print(hm(10,20,30))
还有一种就是参数带两个星号 **
加了两个星号 ** 的参数会以字典的形式导入。基本语法如下:
def printinfo( arg1, **vardict ):
"打印任何传入的参数"
print ("输出: ")
print (arg1)
print (vardict)
# 调用printinfo 函数
printinfo(1, a=2,b=3)
局部函数及用法(包含nonlocal关键字)
通过 nonlocal 语句即可声明访问赋值语句只是访问该函数所在函数内的局部变量。
def foo ():
# 局部变量name
name = 'Charlie'
def bar ():
# 访问bar函数所在的foo函数的name局部变量
print(name) # Charlie
name = '孙悟空'
bar()
foo()
#UnboundLocalError: local variable 'name' referenced before assignment
#该错误是由局部变量遮蔽局部变量导致的,在 bar() 函数中定义的 name 局部变量遮蔽了它所在 foo() 函数内的 name 局部变量,又因为 bar() 函数中的 name 局部变量定义在 print() 输出函数之后,使的 print(name) 执行时找不到合适的 name,因此导致程序报错。
def foo ():
# 局部变量name
name = 'Charlie'
def bar ():
nonlocal name
# 访问bar函数所在的foo函数的name局部变量
print(name) # Charlie
name = '孙悟空'
print(name)#孙悟空
bar()
foo()
内嵌函数与闭包
- global关键字
使用global关键字,可以在函数里面修改全局变量
a=5
def foo ():
a=10
print(a)#10
foo()
print(a)#5
a=5
def foo ():
global a
a=10
print(a)#10
foo()
print(a)#10
- 内嵌函数
函数定义允许在函数内部创建另一个函数,这种函数称作内嵌函数
def foo ():
def a():
print(5**2)
a()
foo()#25
- 闭包
闭包是函数式编程的一个重要语法结构不同语言的实现闭包的方式不同
python中如果一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就认为是闭包
def foo(x):
def a(y):
return x*y
return a
print(foo(5)(6))#30
使用闭包时注意:闭包的概念就是由内部函数而来的所以不能在外部函数以外引用内部函数
print(a(9))
#NameError:name 'a' not defined
在闭包中,外部函数的局部变量对应内部函数的局部变量,类似于全局变量与局部变量的关系,但在内部函数中只能对外部函数的局部变量进行引用而不能进行改变
def funx():
x=5
def funy():
x *= x
return(x)
return funy()
print(funx())#UnboundLocalError: local variable 'x' referenced before assignment
python认为内部函数的x是局部变量时,外部函数的x就被屏蔽了起来,所以执行x*=x时候,在右边就找不到局部变量x的值,因此报错
解决方法
- 间接使用容器类型来存放,因为容器类型不是放在栈里,所以当栈消失时不会消失。
def funx():
x=[5]
def funy():
x[0] *= x[0]
return x[0]
return funy()
print(funx())#25
- 内部函数修改外部函数里的局部变量使用nonlocal关键字,使用方法与global一样
def funx():
x=5
def funy():
nonlocal x
x *= x
return(x)
return funy()
print(funx())#25
函数使用方法(高级用法)
lambda表达式(匿名函数)及用法
匿名函数用来简化局部函数
基本形式
lambda [parameter_list]:返回值
冒号右边为原函数参数,可以为空,当是多函数时候用逗号分隔开
冒号右边为返回值
def hm(x,y):
return x**y
print(hm(2,3))#8
#运用lambda表达式
a=lambda x,y:x**y
print(a(2,3))#8
filter(),map()
- filter()
通过该函数可以只保留感兴趣的信息,并将不感兴趣的东西丢掉,可以称作过滤器
filter有两个参数:第一个参数可以是一个函数也可以是None,如果是一个函数的话,则将第二个可迭代数据里的每一个元素作为函数的参数进行计算,把返回Ture的值筛选出来;如果第一个参数为None的话,直接将第二个参数中为Ture的值筛选出来。
#第一个参数为函数时候
def hm(x):
return x%2
a=filter(hm,range(10))
print(list(a))#[1, 3, 5, 7, 9]
#第一个参数为None
b=filter(None,[1,0,False,None,'yu'])
print(list(b))#[1, 'yu']
#使用lambd匿名函数
c=filter(lambda x:x%2,range(10))
print(list(c))#[1, 3, 5, 7, 9]
- map()
- map在编程领域一般做“映射”来解释,map()这个内置函数也是有两个参数,仍然一个为函数和一个是可迭代序列,将序列的每一个元素作为参数代入到函数里面进行运算加工直到最后一个元素,返回所有加工后的元素构成的新序列
c=map(lambda x:x%2,range(10))
print(list(c))#[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
递归函数
简单来说就是函数调用自身
#阶乘函数
def a(x):
if x==1:
return 1
else:
return x*a(x-1)
x=int(input("请输入一个值:"))#10
print(a(x))#3628800
eval()和exec()函数
eval() 和 exec() 函数的功能是相似的,都可以执行一个字符串形式的 Python 代码(代码以字符串的形式提供),相当于一个 Python 的解释器。二者不同之处在于,eval() 执行完要返回结果,而 exec() 执行完不返回结果(文章后续会给出详细示例)。
- eval()
eval(expression, globals=None, locals=None, /)
- exec()
exec(expression, globals=None, locals=None, /)
- expression:这个参数是一个字符串,代表要执行的语句 。该语句受后面两个字典类型参数 globals 和 locals 的限制,只有在 globals 字典和 locals 字典作用域内的函数和变量才能被执行。
- globals:这个参数管控的是一个全局的命名空间,即 expression 可以使用全局命名空间中的函数。如果只是提供了 globals参数,而没有提供自定义的 __ builtins__,则系统会将当前环境中的 __ builtins __复制到自己提供的 globals中,然后才会进行计算;如果连 globals 这个参数都没有被提供,则使用 Python 的全局命名空间。
- locals:这个参数管控的是一个局部的命名空间,和 globals 类似,当它和 globals 中有重复或冲突时,以 locals的为准。如果 locals 没有被提供,则默认为 globals。