python函数
函数
概念:功能 (包裹一部分代码 实现某一个功能 达成某一个目的)
特点:可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
1.函数基本格式
# 定义一个函数 def 函数名():
code1
code # 调用函数 函数名() """ # 定义函数
def func():
print("我是一个函数 ... ")
# 调用函数
func()
2.函数的命名
字母数字下划线,首字符不能为数字
严格区分大小写,且不能使用关键字
函数命名有意义,且不能使用中文哦
驼峰命名法:
(1) 大驼峰命名法: 每个单词的首字符要大写 (类的命名)
mycar => MyCar
(2) 小驼峰命名法: 除了第一个单词首字符小写外,剩下单词首字符大写 (函数或者变量)
mycar => myCar
(3)_命名法:可以将不同的单词用_拼接在一起
mycar => my_car
symmetric_differencesymmetricDifference SymmetricDifference
# 函数定义 def cfb_99(): for i in range(1,10 ): for j in range(1,i+1 ): print ( " {:d}*{:d}={:2d} " .format(i,j,i*j) ,end= "" ) print () # 调用函数 for i in range(5 ):
cfb_99()
函数的参数
参数: 函数运算时需要的值
参数种类:
(1)形参: 形式参数,在函数的定义处
(2)实参: 实际参数,在函数的调用处
形参的种类:
1.普通形参(位置形参) 2.默认形参 3普通收集形参 4.命名关键字形参 5.关键字收集形参
实参的种类:
1.普通实参 2.关键字实参
原则:
形参和实参要一一的对应
1.普通形参(位置形参)
# 定义函数 """ hang,lie普通形参,在函数定义处 """ def small_star(hang,lie):
i = 0 while i < hang:
j = 0 while j < lie: print ( " * " ,end= "" )
j +=1 print ()
i += 1 # 调用函数 """ 10,10普通实参,在函数的调用处 """ small_star( 10,10 )
small_star( 2,3)
2.默认形参
""" hang,lie默认形参,在函数定义处 """ """ 如果给予实参,那么使用实参
如果没有给予实参,那么使用参数身上的默认值 """ def small_star(hang=10,lie=10 ):
i = 0 while i < hang:
j = 0 while j < lie: print ( " * " ,end= "" )
j +=1 print ()
i += 1 small_star( 4,8 )
small_star( 8 )
small_star()
3.普通形参 + 默认形参
""" 普通形参必须写在默认形参的前面不能调换位置 """ def small_star(hang,lie=10 ):
i = 0 while i < hang:
j = 0 while j < lie: print ( " * " ,end= "" )
j +=1 print ()
i += 1 small_star( 5,7 ) # small_star(5) # small_star() error
4.关键字实参
1.如果都是关键字实参,可以任意调整实参的顺序
2.普通实参必须写在关键字实参的前面
def small_star(hang,a,b,c,lie=10 ):
i = 0 while i < hang:
j = 0 while j < lie: print ( " * " ,end= "" )
j +=1 print ()
i += 1 # hang a ... lie 具体指定参数的值叫做关键字实参,在函数的调用处; # small_star(hang=3,a=4,b=5,c=6,lie=7) # small_star(b=5,c=6,lie=7,a=4,hang=3) small_star(3,4,b=5,c=6,lie=7 )
small_star( 3,4,b=5,lie=7,c=6 ) # small_star(b=5,c=6,lie=7,3,4) error
收集参数
(1) 普通收集形参
专门用来收集那些多余的没人要的普通实参 收集之后,会把多余实参打包成一个元组 参数头上1个星星
def func(*args):
pass
args => arguments
def func(a,b,c,* args): print (a,b,c) # 1 2 3 print (args) # (4,5,6) func( 1,2,3,4,5,6 ) # 任意个数值得累加和 def mysum(* args):
total = 0 for i in args:
total += i print (total)
mysum( 1,2,3,4,4,45,10,100)
(2) 关键字收集形参
专门用来收集那些多余的没人要的关键字实参收集之后,会把多余关键字实参打包成一个字典,参数头上有2个星星
def func(**kwargs):
pass
kwargs => keyword arguments
def func(a,b,c,** kwargs): print (a,b,c) print (kwargs) # {'f': 100, 'e': 200, 'z': 12} func(c=1,a=3,b=10,f=100,e=200,z=12)
拼接任意个数值变成字符串
"""
班长: 赵万里
班花: 马春陪
划水群众: 赵沈阳,李虎凌,刘子涛
"""
def func(**kwargs):
strvar1 = ""
strvar2 = ""
# 定义职位信息
dic = {"monitor":"班长","classflower":"班花"}
print(kwargs)
# 共5次循环
for k,v in kwargs.items():
if k in dic:
# 将2次循环的结果通过+= 拼接在一起
strvar1 += dic[k] + ":" + v + "\n"
else:
# 将3次循环的结果通过+= 拼接在一起
strvar2 += v + " , "
print(strvar1.strip())
print("划水群众:",strvar2.strip(" , "))
"""
# print(k,v)
k v
monitor 赵万里
classflower 马春陪
water1 赵沈阳
water2 李虎凌
water3 刘子涛
{'monitor': '赵万里', 'classflower': '马春陪', 'water1': '赵沈阳', 'water2': '李虎凌', 'water3': '刘子涛'}
"""
func(monitor="赵万里",classflower="马春陪",water1="赵沈阳",water2="李虎凌",water3="刘子涛")
命名关键字参数
(1) def func(a,b,*,c,d) 跟在*号后面的c和d是命名关键字参数
(2) def func(*args,e,**kwargs) 加在*args和**kwargs之间的参数都是命名关键字参数
命名关键字参数 : 在调用函数时,必须使用关键字实参的形式来进行调用;
定义方法一
def func(a,b,* ,c,d): print (a,b) print (c,d) # 必须指定关键字实参,才能对命名关键字形参进行赋值 func(1,2,c=3,d=4)
定义方法二
def func(*args,e,** kwargs): print (args) # (1, 2, 3, 4) print (e) # 3 print (kwargs) # {'a': 1, 'b': 2} func(1,2,3,4,a=1,b=2,e=3)
星号的使用
* 和 ** 如果在函数的定义处使用:* 把多余的普通实参打包成元组,** 把多余的关键字实参打包成字典
* 和 ** 如果在函数的调用处使用:* 把元组或者列表进行解包,** 把字典进行解包
def func(a,b,* ,c,d): print (a,b) print (c,d)
tup = (1,2 ) # 函数的调用处 *号用法 func(*tup,c=3,d=4) # func(1,2,c=3,d=4) # 函数的调用处 **号用法 dic={ " c " :3, " d " :4 }
func( 1,2,**dic) # func(1,2,c=3,d=4) # 综合写法 # 函数的调用处 tup = (1,2 )
dic ={ " c " :3, " d " :4 }
func( *tup,** dic) # 定义成如下形式,可以收集所有的实参 def func(*args,** kwargs): pass
总结:
当所有的形参都放在一起的时候,顺序原则:普通形参 -> 默认形参 -> 普通收集形参 -> 命名关键字形参 -> 关键字收集形参
def f1(a, b, c=0, *args, ** kw): print ( ' a = ' , a, ' b = ' , b, ' c = ' , c, ' args = ' , args, ' kw = ' , kw) def f2(a, b, c=0, *, d, ** kw): print ( ' a = ' , a, ' b = ' , b, ' c = ' , c, ' d = ' , d, ' kw = ' , kw)
# 以上两个函数 打印结果 # (一) f1(1, 2) # a =1 b=2 c=0 args=() kw={} f1(1, 2, c=3) # a=1,b=2,c=3,args=() kw={} f1(1, 2, 3, ' a ' , ' b ' ) # a=1 b=2 c=3 args=(a,b) kw={} f1(1, 2, 3, ' a ' , ' b ' , x=99) # a=1 b=2 c=3 args=(a,b) kw={x:99} f2(1, 2, d=99, ext=None) # a=1 b=2 c=0 d=99 kw={ext:None} # (二) args = (1, 2, 3, 4 )
kw = { ' d ' : 99, ' x ' : ' # ' } # f1(1,2,3,4,d=99,x=#) f1(*args, **kw) # a=1 b=2 c=3 args=(4,) kw={d:99,x:#} # (三) myargs = (1, 2, 3 )
mykw = { ' d ' : 88, ' x ' : ' # ' } # f2(1,2,3,d=88,x=#) f2(*myargs, **mykw) # a=1,b=2,c=3 d=88 kw={x:#} # (四) def f1(a, b, c=0, *args,d,** kw): print ( ' a = ' , a, ' b = ' , b, ' c = ' , c, ' args = ' , args, ' kw = ' , kw) print (d)
f1( 1,2,3, ' a ' , ' b ' ,d=67, x=99,y=77) # a=1 b=2 c=3 args=(a,b) kw={x:99,y:77} # d=67
return 自定义函数的返回值
概念:return 把函数内部的数据返回到函数的外面,返回到函数的调用处
1.return + 六大标准数据类型 , 除此之外还可以返回函数 或者 是类对象
2.return 在执行时,意味着终止函数,后面的代码不执行.
3.如果不定义return返回值,默认返回None
(1) return + 六大标准数据类型
def func(): # return 111 # return 6.89 # return "你好帅啊,我爱死你乐" # return [1,2,3] # return {"a":1,"b":2} return 1,2,3 # 返回元组 res = func() print (res)
(2) return 在执行时,意味着终止函数,后面的代码不执行.
def func(): print (1 ) print (2 ) return 3 print (4 )
res = func() print (res) def func(): for i in range(5 ): if i == 3 : return 4 print (i)
res = func() print (res)
(3) 如果不定义return返回值,默认返回None
def func(): pass res = func() print (res) # None # 注意点 打印的数据和返回的数据不是等价的,返回的数据是可以自定义的; res = print (1234 ) print (res) # None
模拟+-*/计算器
""" 功能: 完成计算
参数: 2个数字和运算符
返回值: 计算后的结果 """ def calc(num1,num2,sign): if sign == " + " : return num1 + num2 elif sign == " - " : return num1 - num2 elif sign == " * " : return num1 * num2 elif sign == " / " : if num2 == 0: return " 除数不能为零 " return num1 / num2 else : return " 抱歉,超出了我的运算范围. " res = calc(3,5, " + " )
res = calc(3,5, " - " )
res = calc(3,5, " * " )
res = calc(3,0, " / " )
res = calc(3,0, " & " ) print (res)
全局变量和局部变量
1.概念
局部变量:在函数内部定义的变量就是局部变量
全局变量:在函数外部定义的变量或者在函数内部使用global关键字声明是全局变量
2.作用域:
局部变量的作用范围仅仅在函数的内部
全局变量的作用范围横跨整个文件
3.生命周期:该变量的作用时长
内置命名空间 -> 全局命名空间 -> 局部命名空间 (开辟空间顺序)
内置属性 > 全局属性 > 局部属性 (作用时长:长->短)
1 局部变量
def func():
# 定义一个局部变量
a = 1
# 获取当前的局部变量
print(a)
# 修改一个局部变量
a = 2
print(a)
func()
# print(a) error
2.全局变量
# 定义一个全局变量 b = 10 # 获取当前的全局变量 print (b) # 修改一个全局变量 b = 20 print (b) def func(): print (b)
func()
3.函数内部定义全局变量
def func(): global c
c =30 func() print (c)
4.函数内部修改全局变量
d = 50 def func(): global d
d = 51 func() print (d)
总结:
global的使用如果当前 不存在 全局变量,可以在函数内部通过global关键字来定义全局变量,如果当前 存在 全局变量,可以在函数内部通过global关键字来修改全局变量
函数名的使用
python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限
def func():
print( "我是func函数")
(1)动态创建
a = 1 print (a)
a = func
a()
(2)动态销毁
del a # a() # func()
(3)当参数传递
def func2(): return " 我是func2函数 " def func1(f): return f() # "我是func2函数" res = func1(func2) print (res)
(4)作为值返回
def func3(): print ( " 我是func3函数 " ) def func4(f): return f
res = func4(func3) print (res)
res()
(5)函数名可以作为容器类型数据的元素
lst = [func,func3] for i in lst:
i()
__doc__ 或者help查看文档
def big_chang_cishen(something): """ 功能: 教你怎么吃大肠
参数: 吃的内容
返回值: 是否满意 """ print ( " 把{}洗一洗 " .format(something)) print ( " 直接找肠子头,放嘴里,吸一下 " ) print ( " 擦擦嘴,满意的放下肠子头 " ) return " 吃完了,真好吃~ " big_chang_cishen( " 生肠子 " ) # 方法一 res = big_chang_cishen. __doc__ print (res) # 方法二 help(big_chang_cishen)
函数的嵌套
互相嵌套的两个函数:包裹在外层的叫做外函数,内层的就是内函数
def outer(): # inner() def inner(): print ( " 我是inner函数 " )
# (1)内部函数可以直接在函数外部调用么 不行
# inner()
# (2)调用外部函数后,内部函数可以在函数外部调用吗 不行
# outer()
# inner()
# (3)内部函数可以在函数内部调用吗 可以
outer()
# (4)内部函数在函数内部调用时,是否有先后顺序 有的
# 先定义在调用
# 在其他语言中有预加载的机制,提前把函数驻留到内存中,然后再去编译脚本内容
# python没有预加载函数的机制,只能先定义在调用;
外函数是outer 中间函数是inner 最里层是smaller ,调用smaller函数
def outer(): def inner(): def smaller(): print ( " 我是smaller函数 " )
smaller()
inner()
outer()
LEGB 原则
def outer(): def inner(): def smaller(): print (a)
smaller()
inner()
outer()
LEGB原则(就近找变量原则)
找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间 (内建作用域)
G —— Global(module); 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
nonlocal的使用 (用来修改局部变量)
nonlocal遵循LEGB原则
(1) 它会找当前空间上一层的变量进行修改
(2) 如果上一层空间没有,继续向上寻找
(3) 如果最后找不到,直接报错
(1)它会找当前空间上一层的变量进行修改
def outer():
a = 10 def inner():
nonlocal a
a = 20 print (a)
inner() print (a)
outer()
(2)如果上一层空间没有,继续向上寻找
def outer():
a = 20 def inner():
a = 15 def smaller():
nonlocal a
a = 30 print (a)
smaller() print (a)
inner() print (a)
outer()
(3)如果最后找不到,直接报错
'''nonlocal 只能修改局部变量'''
a = 20 def outer(): def inner(): def smaller():
nonlocal a
a = 30 print (a)
smaller() print (a)
inner() print (a)
outer()
error
(4) 不通过nonlocal 是否可以修改局部变量呢?ok
def outer():
lst = [1,2,3 ] def inner():
lst[ -1] = 3000 inner() print (lst)
outer()
闭包函数
互相嵌套的两个函数,如果内函数使用了外函数的局部变量,并且外函数把内函数返回出来的过程叫做闭包。
里面的内函数叫做闭包函数
是不是闭包?
1.内函数用了外函数的那个局部变量
2.外函数返回内函数
1.基本语法形式
def zhaoshenyang_family():
father = " 马云 " def hobby(): print ( " 我对钱没有一丝丝的兴趣,我不看重钱,这是我爸爸{}说的 " .format(father)) return hobby
func = zhaoshenyang_family()
func()
2.闭包的复杂形式
def zhaowanli_family():
gege = " 王思聪 " didi = " 鞋王,高振宁 " money = 1000 def gege_hobby():
nonlocal money
money -= 500 print ( " 我交朋友不在乎他有没有钱,反正都没有我有钱.我就喜欢交女朋友... 钱物还剩下{} " .format(money)) def didi_hobby():
nonlocal money
money -= 400 print ( " 家里有鞋柜,各式各样的奢侈鞋,一双大概20~30万,钱物还剩下{} " .format(money)) def big_master(): return [gege_hobby,didi_hobby] return big_master
func = zhaowanli_family() print (func)
lst = func() print (lst) # 获取哥哥函数 gege = lst[0]
gege() # 获取弟弟函数 didi = lst[1 ]
didi()
3.使用 __closure__ , cell_contents 判定闭包
""" 如果返回的元组中有数据说明是闭包,谁的生命周期被延长就打印谁 """ tup = func. __closure__ print (tup) # 先获取第一个单元格 cell_contents获取对象中的内容 func1 = tup[0].cell_contents print ( " <11111> " ) """ 打印闭包函数didi_hobby中,生命周期被延长的属性 """ print (func1. __closure__ [0].cell_contents)
func1() # 在获取第二个单元格 cell_contents获取对象中的内容 func2 = tup[1 ].cell_contents print ( " <22222> " ) """ 打印闭包函数gege_hobby中,生命周期被延长的属性 """ print (func2. __closure__ [0].cell_contents)
func2()
闭包特点
特点:在闭包函数中,内函数使用了外函数的局部变量,该变量会与内函数发生绑定,延长该变量的生命周期,持续到脚本执行结束.(生命周期和全局变量一样长,但不是全局变量)
def outer(val): def inner(num): return val + num return inner
func = outer(10 )
res = func(15 ) print (res)
闭包的意义
全局变量的作用域大,容易被篡改
num = 0 def click_num(): global num
num += 1 # num = num + 1 print (num)
click_num()
click_num()
click_num()
num = 100 click_num()
click_num()
改造,用闭包来实现
闭包的意义:闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.
def outer():
x = 0 def click_num():
nonlocal x
x += 1 print (x) return click_num
click_num = outer()
click_num()
click_num()
click_num()
x = 100 click_num()
click_num()
匿名函数 lambda表达式
用一句话来表达只有返回值的函数
语法: lambda 参数:返回值
特点: 简介,高效
(1)无参的lambda表达式
def func(): return " 文哥是个帅哥 "
改造
func = lambda : " 文哥是个帅哥 " print ( func() )
(2)有参的lambda表达式
def func(n): return id(n)
改造
func = lambda n : id(n) print ( func(100) )
(3)带有判断条件的lambda表达式
def func(n): if n % 2 == 0: return " 偶数 " else : return " 奇数 "
改造
func = lambda n : " 偶数 " if n % 2 == 0 else " 奇数 " print ( func(44) )
三元运算符
只能表达双向分支 只有if else 比较固定 不灵活的语法
语法: 真值 if 条件表达式 else 假值
如果条件表达式成立为True , 返回if前面的真值,反之,返回else后面的假值
n = 13 res = " 偶数 " if n % 2 == 0 else " 奇数 " print (res)
小练习 : 比较两者之间的最大值进行返回
def func(x,y): if x > y: return x else : return y
改造
func = lambda x,y : x if x>y else y print ( fu