1,return语句
在函数末尾不适用return语句,会默认返回None,且定义函数不能为空,至少要有一个pass语句
示例:
def func():
pass
v = func()
print(v) #None
2,序列传参:
序列传参是指在函数调用过程中,用 * 将序列拆解后按位置传参的形式传递参数
示例:
def myfun(a,b,c):
print(a,b,c)
s = [1,2,3]
myfun(*s)
3,关键字传参:
关键字传参是指传参时,按着形参的名称给形参赋值实参和形参按名称进行匹配
示例:
def myfun(a,b,c):
print(a,b,c)
myfun(b = 22,a = 11,c = 33)
#等同于myfun(11,22,33)
4,字典关键字传参:
是指实参为字典,将字典用**拆解后进行关键字传参(字典的键值必须与形参名一致,且键的个数必须与形参个数相同)
示例:
def myfun(a,b,c):
print(a,b,c)
d = {'c' :33,'b' :22,'a':11}
myfun(**d)
函数的形参定义方式:
位置形参
星号元组形参
命名关键字形参
双星号字典形参
5,函数的综合传参
函数传参方式,在能确定形参能唯一匹配到相应实参的情况下可以任意组合
示例:
def myfun(a,b,c):
pass
myfun(100,*[200,300]) #正确
myfun(*'AB',300) #正确
myfun(100,c = 300,b = 200) #正确
myfun(1,**{'b':2,'c':3}) #正确
myfun(**{'c':3,'b':2},a = 1) #正确
myfun(b = 2,c = 3,1) #错误,不能确定1给谁,
#不指定时默认位置传参
说明:传参时先位置传参,后关键字传参
6,函数的缺省参数
语法:
def 函数名(形参名1=默认实参1,形参名2=默认实参2…)
说明:
(1)缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数
示例:
def test(a,b=10,c): #错误b右侧必须都具有默认参数
pass
(2)缺省参数可以有0个或多个,甚至全部都有缺省参数
#写一个函数可以传入两个实参或三个实参(如果传入两个实参则返回两个实参的和,三个则返回前两个实参对第三个实参求余的值)
def myfun(a,b,c=None):
if c==None:
return a+b
else:
return (a+b)%c
7,星号元组形参:
语法:
def 函数名(*元组形参名):
语句
作用:收集多个的位置传参,类似print函数可以传入任意多个对象
说明:元组形参名通常用:‘args’
示例:
def func(*args):
print('参数的个数是',len(args))
print('args = ',args)
8,命名关键字形参
语法:
def 函数名(*,命名关键字形参):
语句
或def 函数名(*args,命名关键字形参):
语句
作用:所有的参数都必须用关键字传参或字典关键字传参传递
示例:
def fn(*,d,e): #此函数调用时只能命名传入d与e
print('d = ',d) #此处*不能使用
print('e = ',e)
fn(d = 1,e = 2) #正确
fn(1,2,3,d = 4,e= 5) #错误
def fm(*args,d,e):#给d与e加入默认参数就类似与print函数
for i in args:
print(i,end = ' ')
print('d = ',d)
print('e = ',e)
fm(1,2,3,4,5,d = 6,e = 7) #输出1 2 3 4 5
#d = 6,e =7
fm(*'AB',**{'d':100,'e':200}) #正确
fn函数中的只是相当于标识名用来强制后面的形参只能按命名参数传递,没有实际用处。
例如:def f1(a,b,,d,e)
f1(1,2,d = 3,e =4)
9,双星号字典形参:
语法:
def 函数名(**字典形参名):
语句
作用:收集多个关键字参数
说明:常使用kwargs作用形参名
def func(**kwargs):
print('关键字参数个数是',len(kwargs))
print("kwargs = ",kwargs)
func(name='pinkman',age = 15)
#关键字参数个数是:2
#kwargs = {'age':15,'name':'pinkman'}
#综合示例:函数参数自左至右的顺序为:
位置形参,星号元组形参,命名关键字形参,双星号字典形参
可以混合使用,但一定不能位置颠倒
def f1(a,b,*args,c,**kwargs):
pass
f1(1,2,3,4,5,6,c = 7,d =8,e =9) #正确
f1(1,2,3,4,5,6,d =8,e =9,c =10) #正确
f1(*"hello",d=6,**{'c':5,'e':7}) #正确*与**分别
用来分解字符串(或其他可迭代对象)与字典
10,函数的不定长参数:
#可以用接受任何形式的参数
def fn(*args,**kwargs):
pass
练习:自定义简易range函数(只实现正序序列,返回列表)
def myrange(start,stop=None,step=1):
if stop == None: #如果只有一个参数
stop = start
start = 0
i = start
L = []
while i < stop:
L.append(i)
i+=step
return L
11,全局变量与局部变量
局部变量:
定义在函数内部的变量称为局部变量(函数的形参也是局部变量)
局部变量只能在函数内部使用
局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁
全局变量:
定义在函数外部,模块内部的变量称为全局变量
全局变量,所有的函数都可以直接访问(但函数内部不能将其直接赋值,会报错),函数定义的函数名也相当于一个全局变量
a = 100
b = 200
def f1(c):
d = 400
a = 1
print(a) #此时会创建局部变量a,不会修改全局变量a
def f2(c):
print(a)
a = 1 #此时会报错:局部变量在定义之前被引用,
编译器无法区分局部变量与全局变量
局部变量说明:
(1)在函数内首次对变量赋值是创建局部变量,再次为变量赋值是修改局部变量的绑定关系
(2)在函数内部的赋值语句不会对全局变量造成影响
(3)局部变量只能在其被声明的函数内部访问,而全局变量可以在整个模块(整个py文件)范围内访问
12,globals与locals函数
globals()返回当前全局作用域内变量的字典
locals() 返回当前局部作用域内变量的字典
示例:
a = 1
b = 2
c = 3
def f1(c,d):
e = 300
print('locals()返回:',locals())
for k,v in globals().items():
print(k,'-->',v) #顺序打印全局变量字典
print(globals()['c']) #访问全局变量c
13,函数变量
函数名是变量,它在创建函数时绑定一个函数
示例1:
def f1();
print('f1被调用')
fx = f1 #fx绑定f1函数
fx() #调用f1函数
del f1 #相当于删除f1的绑定关系
fx() #仍相当于调用f1
示例2:
def f1():
print('hello')
def f2():
print('world')
f1,f2 = f2,f1 #交换两个变量的绑定关系
f1() #world
f2() #hello
一个函数可以作为另一个函数的参数传递
示例1:
def f1():
print('hello')
def f2():
print('world')
def fx(fn):
print(fn) #打印fn函数的内存地址
fn() #调用fn函数
fx(f1)
示例2:
def fx(a,fn):
return fn(a)
L = [1,7,4,9]
print("最大值是:",fx(L,max))
print("最小值是:",fx(L,min))
print("和是:",fx(L,sum))
函数可以作为另一个函数的返回值
示例:
def get_fx():
s = input('请输入您要做的操作:')
if s=='求最大':
return max
elif s=='求最小'
return min
elif s=='求和'
return sum
L = [2,4,5,7,8,9]
print(L)
f1 = get_fx()
print(f1(L))
练习:自制简单的计算器
def myadd(a,b):
return a+b
def mymul(a,b):
return a*b
def mydivid(a,b):
return a/b
def mysub(a,b):
return a-b
def get_op(op): #根据运算符判断使用什么函数
if op=='+':
return myadd
elif op=='-':
return mysub
elif op=='*':
return mymul
elif op=='/':
return mydivid
def main():
while True:
string = input(“请输入一个简单的算术表达式(用空格隔开):”)
L = string.split() '''str.split()默认去除空格,
且str必须有空格'''
a,op,b = L #迭代依次赋值
a,b = int(a),int(b) #将字符串分隔开的字符转换为整数
fx = get_op(op) #fx为调用的操作数函数
print("结果是:",fx(a,b))
main()
14,函数的嵌套定义
是指一个函数里用def语句来创建其他的函数
示例:
def fn_outter():
print("fn_outter被调用!")
def fn_inner():
print("fn_inner被调用!")
fn_inner()
fn_inner()
print("fn_outter调用结束")
return fn_inner
fn_outter()
#############################
#函数内部函数的调用方法:
fx = fn_outter() #返回内部函数的链接
fx() #调用内部函数
15,python作用域/名字空间
作用域也叫名字空间,是访问变量时,查找变量名的范围空间
python的四个作用域LEGB(依上至下查找)
局部作用域 local function
外部嵌套函数作用域 Enclosing Function Locals
函数定义所在模块(文件)的作用域 Global(Module)
python内置模块的作用域 Builtin(python)
示例1:
v = 100 #全局作用域
def fun1():
v = 200 #外部嵌套函数的作用域
print('fun1内的v = ',v)
def fun2():
v = 300 #局部作用域
print('fun2内的v = ",v)
fun2()
fun1()
print('v = ',v)
变量名的查找规则:从内向外
示例2:
def max(a,b): #全局函数作用域替代内建函数作用域
return 10000
max(100,200) #10000
在默认情况下,对变量名赋值会创建或改变本作用域内的变量。若要想在局部改变全局变量值,需要使用
global语句
作用:告诉解释器,global语句声明的一个或多个变量,这些变量的作用域为模块级的作用域,也称为全局变量;全局声明(global)将赋值变量映射到模块
语法:
global 变量1,变量2,… … … …
示例:
v = 100
def fn():
global v #声明v变量是全局变量
v = 200
fn()
print(v) #v = 200
说明:
(1)全局变量如果要在函数内被赋值,则必须经过全局声明(否则会被认为是局部变量)
(2)全局变量在函数内部不经过声明就可以直接访问
(3)不能先声明局部的变量,再用global声明为全局变量,此做法不符合规则
def f1():
x = 100
global x #解释器会报警,但可以在局部创建全局
def f2():
global x
x =100 #正确,在函数内创建全局变量
(4)global变量列表里的变量不能出现在此作用域内的形参列表里
nonlocal语句
作用:告诉解释器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量1,变量2,… … … …
示例:
var = 100
def f1():
var = 200
print('f1里的var=',var)
def f2():
var = 300 #这里是全局变量,若想修改f1里的var
#需要使用nonlocal语句
#nonloval var
#var = 300
print('f2里的var=',var)
f2()
print('f2调用结束后的var值为',var)
f1()
print('全局var=',var)
nonlocal说明:
(1)nonlocal语句只能在被嵌套函数内部进行使用
示例:
def f1():
nonlocal x
x =100 #错误,nonlocal只能在嵌套函数内使用
(2)访问nonlocal变量将对外部嵌套函数的作用域的变量进行操作
(3)当有两层或两层以上的函数嵌套时,访问nonlocal变量只对最近一层的变量进行操作
示例:
def f1():
v = 100
def f2():
v = 200
def f3():
nonlocal v #在f2中找,如果
v = 300 #找不到则在f1中找
f3()
print('f2最后结束的v是',v) #300
f2()
print('f1最后结束的v是',v) #100
f1()
(4)nonlocal语句变量列表里的变量名,不能出现在此函数的参数列表中
示例:
def f1():
v = 100
def f2(v):
nonlocal v #出错,v已在形参列表中,与nonlocal
#变量冲突
v+=1
f2(20)
f1()
lambda表达式(又称匿名函数)
作用:创建一个匿名函数对象,同def类似,但不提供函数名
语法:
lambda 参数1,参数2,… … …:表达式
[]里的内容可以省略
只能跟一个表达式,不能跟多余语句,且返回表达式的值
示例:
def myadd(x,y):
return x+y
#以上函数可以改写为:
myadd = lambda x,y:x+y
print('2+3=',myadd(2,3)) #5
(lambda x,y:x+y)(2,3) #5
fx = lambda : print('hello')
fx() #hello
说明:
(1)lambda知识一个表达式,它用来创建一个函数对象
(2)当lambda表达式调用时,先执行冒号后(:)的表达式,并返回表达式的结果的引用
(3)lambda表达式创建的函数只能包含一条“表达式”
(4)lambda比函数简单,且可以随时创建和销毁,有利于减少程序的耦合度(各个函数与模块的牵连关系)
示例1:
#函数名的覆盖
def mymax(x,y):
print("mymax被调用")
return x if x>y else y
mymax = lambda x,y:x if x>y else y #mymax变量名覆盖
#上面的函数
print(mymax(100,200))
示例2:
#lambda的其他用法(匿名函数不会创建变量不会占用内存空间,临时函数使用lambda创建)
def fx(f,x,y):
print(f(x,y))
fx((lambda a,b:a+b),x,y)
fx((lambda a,b:a*b),x,y)
16,eval()和exec()函数
eval()函数
格式:eval(source,global=None,locals=None)
作用: 把一个字符串当成一个表达式来执行,返回表达式执行后的结果,若字符串不是表达式就会出错
示例:
x = 100
y = 200
a = eval('x+y')
print(a)
exec()函数
作用:把一个字符串当成程序执行
格式:exec(source,globals=None,locals=None)
示例:
x = 100
y = 200
s = 'z = x+y;print(z);del z;
print("删除成功")'
exec(s)
print(z) #且z变量还存在
eval和exec的两个参数globals和locals
此两个参数是用来设置’表达式’或’程序’运行的全局变量和局部变量。且globals和locals变量传递参数必须为字典
示例:
x = 100
y = 200
s = 'print(x,y,x+y)'
exec(s) #100 200 300
exec(s,{'x':10,'y':20}) #10 20 30
exec(s,{'x':10},{'x':1,'y':2}) #1 2 3局部优先执行
exec(s,{'x':10},{'y':2}) #10 2 12
17,函数式编程
函数式编程是指用一系列函数决定问题
函数本身可以赋值给变量,赋值后变量绑定函数
允许将函数本身作为参数传入另一个函数
允许返回一个函数
#示例:
print(sum(range(1,101))) #打印1到100之间的整数的和
具体要求:
重入性、功能单一、互不影响等
(1)函数的可重入性:
可重入是指一个函数传的参数一定,则结果必须一定,保证函数调用之间的耦合性,不相互影响
要求:
def定义的函数不要访问除局部变量以外的变量
示例:
#不可重入的函数
y = 200
def myadd(x):
return x+y
print(myadd(10)) #210
y = 300
print(myadd(x+y)) #310
#可重入的函数
def myadd(x,y):
return x+y
print(myadd(10,20))
(2)高阶函数:
满足下列一个条件的函数即为高阶函数:
一、函数接受一个或多个函数作为参数传入
二、函数返回一个函数
python中内建(builtins)的高阶函数:map,filter,sorted
- map函数:
map(func,*iterables)用函数对可迭代对象中的每一个元素作为参数计算出新的可迭代对象并返回,当最短的一个可迭代对象不再提供数据时,此可迭代对象生成结束
*iterable(表示可传入任意多个可迭代对象)
示例1:
def pow2(x):
return x**2
for x in map(pow2,range(1,10)):
print(x) #1 4 9 16 25 36 49 64 81
示例2:
#演示多个iteralbe对象的map处理
#生成1**4,2**3,3**2,4**1
#使用内建的pow(x,y,z=None)
for x in map(pow,range(1,10),range(4,0,-1)):
print(x)
#1 8 9 4 当range(4,0,-1)不再提供对象时结束
for x in map(pow,[2,3,5,7],[4,3,2,1],range(5,10)):
print(x)
#求幂指数的余数
练习:
#求1**2 +2**2 +3**2 +4**2 +5**2 +6**2 +7**2 +8**2 +9**2
#由于map需要iterable对象,所以可以编写函数只提供一个可迭代对象
#方法1
def pow2(x):
return x**2
print(sum(map(pow2,range(1,10))))
#方法2 : 不用编写函数
print(sum(map(lambda x:x**2,range(1,10))))
- filter函数
格式:filter(func,iterable)
作用:筛选可迭代对象iterable中的数据,返回一个可迭代对象,此可迭代对象将对iterable进行筛选(可迭代对象属性不固定,故若要list对象需要对函数使用list构造函数)
说明:函数func将对每个元素进行求值,返回False则将此数据丢弃,返回True则保留数据
示例:
def isodd(x): #此函数判断x是否为奇数
return x%2==1
for x in filter(isodd,range(10)):
print(x) #1,3,5,7,9
even = [x for x in filter(lambda x:x%2==0,range(10))]#偶数
练习:将1~100之间素数放到列表中
def isprime(x):
if x<=1:
return False
for i in range(2,x):
if x%i==0:
return False
return True
L = list(filter(isprime,range(1,101)))
- sorted函数
作用:将原可迭代对象的数据进行排序,生成排序后的列表
格式:sorted(iterable,key=None,reverse=False)
说明:
iterable可迭代对象
key的参数是一个函数名,是用来提供一个参考值的,这个值将作为排序的依据
reverse标志用来设置是否降序排序
示例:
L = [5,-2,-4,0,3,1]
L2 = sorted(L) #L2 = [-4,-2,0,1,3,5]
L3 = sorted(L,reverse=True) #L3 = [5,3,1,0,-2,-4]
L4 = sorted(L,key=abs) #L4 = [0,1,-2,3,-4,5]
#按名字长度以及字母顺序升序
names = ['jerry','tom','kittys','lebrons']
names1 = sorted(names)
names2 = sorted(names1,key=len)
#按名字最后一个字母的先后顺序排列
names = ['jerry','tom','kittys','lebrons']
def fx(name):
return name[::-1]
name = sorted(names,fx) #['tom','lebrons','kittys','jerry']
#name = sorted(names,lambda name:return name[::-1])
- 递归函数 recursion
python默认递归深度为1000
练习:
#已知有列表L = [[3,5,8],10,[[13,14,[1,2,3]],15,18],20]
L = [[3,5,8],10,[[13,14,[1,2,3]],15,18],20]
list_sum = 0
#编写一个函数打印出所有元素 type(obj) 返回obj的类型
def print_list(lst):
for obj in lst:
if type(obj) is list:
print_list(obj) #如果仍是列表,调用自身
else:
print(obj,end=' ')
#编写一个函数求所有元素的和
def sum_list(lst):
for obj in lst:
if type(obj) is list:
sum_list(obj)
else:
global list_sum #如果是整数,使用全局变量叠加
list_sum+=obj
- 闭包closure
将内嵌函数的语句和这些语句的执行环境打包在一起时,得到的对象称为闭包(closure)【python特有的特性】,用来基于不同的参数批量的生产不同函数
闭包必须满足三个条件:
(1)必须有一个内嵌函数
(2)内嵌函数必须引用外部函数中的变量
(3)外部函数返回值必须是内嵌函数
说明:能够重复使用外部函数的局部变量,不随着调用结束而消失
示例1:
def make_power(y):
def fx(arg): #必须有一个内嵌函数
return arg**y #内嵌函数必须引用外部函数中的变量
return fx #外部函数的返回值必须是内嵌函数
pow2 = make_power(2) #局部变量y绑定为2后不会消失
print('3的平方是:',pow2(3))
pow3 = make_power(3)
print('3的立方是',pow3(3))
示例2:
#使用闭包来描述二元一次方程y = ax**2+bx+c
def func(a,b,c):
def fx(x):
return a*x**2+b*x+c
return fx
#创建一个 y = 4x2 + 5x + 6
fx1 = func(4,5,6)
print(fx1(1)) #x = 1时函数的值
- 装饰器 decorators
函数装饰器是指装饰的是一个函数,传入的是一个函数,返回的也是一个函数的函数
函数装饰器的语法(调用方根据需求想要修改函数功能):
def 装饰器函数名(参数):
语句块
return 函数对象
被装饰函数的语法(编写的原始函数代码)
@装饰器函数名
def 函数名(形参列表):
语句块
示例:
#定义一个装饰器函数,在不修改小张函数代码的前提下修改功能
def mydeco(fn):
def fx():
print('+++++++++++')
fn()
print('-------------------')
return fx
#定义函数的地方(可能是小张写的)
#被mydeco函数装饰
@mydeco #相当于myfunc = mydeco(myfunc)
def myfunc(): #虽然@语句写在了上面,实际上在函数定义后执行
print('myfunc被调用')
#调用函数的地方是小李,调用已经被装饰的函数
myfunc()
#调用函数的地方是小王,调用已经被装饰的函数
myfunc()
带有参数的装饰器及应用案例:
#此示例示意带有参数的装饰器及应用案例
#银行业务:
# 存钱:
# savemoney
# 取钱:
# withdraw
#1,添加一个余额变动提醒短消息功能
def messend_send(fn):
def fx(name,x):
print('发送消息:',name,'来银行办理业务...')
fn(name,x)
print(‘发送消息:’,name,'办了',x,'元的业务...')
return fx
#2,添加权限验证功能的装饰器(验证金额与权限的匹配度)
def privilige_check(fn):
def fx(name,x):
print('正在检查权限.....')
if True;
fn(name,x)
return fx
@privilige_check #第一层装饰,可以装饰多层
@messend_send
def savemoney(name,x):
print(name,'存钱',x,'元')
@privilige_check
@messend_send
def withdraw(name,x):
print(name,'取钱',x,'元')
savemoney('小李',200)
#正在检查权限.....
#发送消息:小李来银行办理业务...
#小李存钱200元
#发送消息:小李办了200元的业务
- 函数的文档字符串
函数内部,第一个没有赋值给任何变量的字符串为文档字符串,
目的是编写函数的用法,提供给调用方查看,例如help(func)
语法:
def 函数名(形参列表):
'''函数的文档字符串''' #单引三引都可以,三引方便换行
函数语句块
示例:
def cba():
'''这是一个文档字符串'''
pass
>>>heklp(cba)
函数的__doc__属性
__doc__属性用来绑定该函数的文档字符串
__name__属性绑定函数名字的字符串(lambda函数名均为lambda)
示例:
def fx():
'''我是一个文档字符串'''
print(fx.__doc__)
fx() #我是一个文档字符串
print(print.__doc__) #显示print函数内的文档字符串
函数总体框架:
[@装饰器名1]
[@装饰器名2]
...
def 函数名([位置形参],[*[元组形参名]],
[命名关键字形参],[**字典形参]):
'''文档字符串'''
语句块
#注:[]里的内容代表可省略
面试题:
L = [1,2,3]
def f(n,lst=[]):
lst.append(n)
print(lst)
f(4,L) #[1,2,3,4]
f(5,L) #[1,2,3,4,5]
f(100) #[100]
f(200) #[100,200]
说明:
此处的f(200)执行结果跟其他语言不同,python的缺省参数不会重新建立,默认参数(缺省参数)绑定在函数对象内部,且随函数的声明一致存在
解决办法:为了保证函数的可重入性,将缺省参数赋为None
def f(n,lst=None):
if lst is None:
lst = []
lst.append(5)
print(lst)