函数简介
函数是python程序重要的组成单元,一个Python程序可以由多个函数组成。
每个函数建议只实现一个功能,这样后续调用中,会更好地减少程序的耦合性,也会提高后续维护效率。
函数形式主要有递归函数、嵌套函数、匿名函数等,以下是本期将主要的函数类型。
1. 递归函数
在函数体内部直接或者间接的自己调用自己,称为递归函数。
每个递归函数必现要包含两个部分:
- 终止条件
表示递归什么时候结束,一般用于返回值,不用调用自己。否则程序会陷入到死循环,异常退出 - 递归步骤
把第 n 步的值和第 n-1 步相关联,类似与我们的数学归纳法
递归函数由于会创建大量的函数对象,过量的消耗内存和运算能力,在处理大量数据时,应避免使用
1.1 递归函数底层
递归函数在没有满足终止条件之前,一直不断调用自己,创建函数栈帧,直到满足终止条件为止
才会继续执行后面的步骤,越早创建的越晚输出结果。
我们来看看一个小栗子
def func1(n):
print("func1:",n)
if n==0:
print("game over")
else:
func1(n-1)
print("func1***",n)
func1(5) #调用函数func1
- 首先在堆内存中创建函数func1对象
- 调用func1()函数,初始化 n 传入的对象是5
- 执行过程中,每调用一次函数本身时就会创建一个函数栈帧,直到遇到终止调用函数为止之后,再继续执行后面的步骤
1.2 递归函数实操
学习了上一节,我们知道了递归函数的运行逻辑,那么我们来小试牛刀一下
【经典】计算阶乘
def function(n):
if n==1:
return 1
else:
return n*function(n-1)
print(function(5))
2.嵌套函数
在函数内部定义的函数,称为嵌套函数,也叫内部函数。
嵌套函数的使用范围原则是在哪产生就在哪使用,具体格式如下
def func1():
# 定义嵌套函数func2
def func2():
func2代码块
func2() #只能在func1函数里调用func2函数
嵌套函数的特点
-
封装-数据隐藏
外部无法访问
def out():
print("out")
def inner():
print("inner")
inner()
out()
inner() # 在函数外调用,程序会报Nameerror
-
贯彻 DRM 原则
DRM:Don't repeat yourself
嵌套函数,可以让 我们在函数内容避免重复代码
# 中文名字
def print_chinesename(firstname,lastname):
print("{0} {1}".format(firstname,lastname))
# 英文名字
def print_englishname(lastname,firstname):
print("{0} {1}".format(lastname,firstname))
使用嵌套函数,就减少重复的代码,只用定义一个函数就可以实现上面的需求
def print_name(ischinese,firstname,lastname):
def inner_print(a,b):
print("{0} {1}".format(a,b))
if ischinese:
inner_print(firstname,lastname)
else:
inner_print(lastname,firstname)
print_name(True,"掘","金")
print_name(False,"Clinton","Bill")
- 闭包
一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行
-
闭包必须嵌套在一个函数里,必须返回一个调用外部变量的函数对象,
具体写法:return后面只写嵌套函数名,不能写括号
def out():
print("out")
def inner():
print("inner")
return inner #直接返回函数对象
3.eval()函数
3.1 eval函数介绍
eval()函数在我们的工作中也是经常使用的函数。
主要的功能:将字符串str 当成有效的表达式来求值并返回计算结果
参数:
source: 一个python表达式或者函数,compile()返回的代码对象
globals: 可选,必现是dictionary
locals:可选,任意映射对象
eval()函数通常用于处理不同来源代码,如客户端或者文件里面的代码断,这样处理就比较灵活。
3.2 eval()函数操作
eval()函数可以处理任意表达式或代码的数据并返回处理结果。
(1)在可选参数缺省的情况下执行
a = "JueJing"
print(eval('a+"30Day"'))
(2)指定global参数情况下
a = "JueJing"
g = {'a':"Bob"} # 指定作用域
print(eval('a+" Jions 30Day"',g))
(3)指定locals参数情况下
当locals和globals起冲突时,locals是起决定作用的,这在很多编程语言里都是一样的,是作用域的覆盖问题,当前指定的小的作用域会覆盖以前大的作用域。
a = 1
b = 2
c = 3
g = {"a":10,"b":20}
l = {"b":200,"c":300}
print(eval('a+b+c',g,l))
4. lambda函数
4.1 lambda函数分析
lambda表达式用来声明匿名函数。
lambda函数是一种简单的,在同一行中定义函数的方法。
lambda函数实际生成了一个函数对象。
lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值
lambda表达式基本语法
lambda argument1,argument2,argument3,....:<表达式>
lambda函数可以大大节省内存空间,避免不要的对象创建,提高效率
# 定义一个lambda函数
m = lambda a,b,c,d:a+b+c
def test(a,b,c,d):
return a+b+c+d
print(test(1,2,3,4))
4.2 lambda函数常见操作
Lambda函数可以具有任意数量的参数,但只能有一个表达式。
(1)直接赋给一个变量,然后再像一般函数那样调用
m = lambda a,b,c,d:a+b+c
print(m)
(2)将lambda函数作为参数传递给其他函数比如说结合map、filter、sorted、reduce等
fliter(lambda x:x%3==0,[1,2,3,4,5,6])
squares = map(lambda x:x**2,range(5))
#使用sorted按照第一个元素排序
>>> a=[('b',3),('a',2),('d',4),('c',1)]
>>> sorted(a,key=lambda x:x[0])
>>> [('a',2),('b',3),('c',1),('d',4)]
# 与reduce函数结合使用
from functools import reduce
print(reduce(lambda a,b:'{},{}'.format(a,b),[1,2,3,4,5,6,7,8,9]))
(3)嵌套使用将lambda函数嵌套到普通函数中,lambda函数本身做为return的值
def increment(n):
return lambda x:x+n
f=increment(4)
f(2)
6
(4)字符串联合,有默认值,也可以用x=(lambda...)这种格式
>>> x=(lambda x='Boo',y='Too',z='Z00':x+y+z)
>>> print(x('Foo'))
>>> 'FooTooZoo'
(5)在tkinter中定义内联的callback函数
import sys
from tkinter import Button,mainloop
x=Button(text='Press me',command=(lambda :sys.stdout.write('Hello,World\n')))
x.pack()
x.mainloop()
(6)判断字符串是否以某个字母开头有
Names = ['Anne', 'Amy', 'Bob', 'David', 'Carrie', 'Barbara', 'Zach']
B_Name= filter(lambda x: x.startswith('B'),Names)
print(B_Name)
['Bob', 'Barbara']
(7)求两个列表元素的和
a = [1,2,3,4]
b = [5,6,7,8]
print(list(map(lambda x,y:x+y, a,b)))
>>> [6,8,10,12]
(8)求字符串每个单词的长度
>>> sentence = "Welcome To JueJing!"
>>> words = sentence.split()
>>> lengths = map(lambda x:len(x),words)
>>> print(list(lengths))
[7, 2, 8]
>>>
总结
本期介绍的几种函数类型是我们工作中常用的,掌握好它们,能让我们的工作事半功倍哦
好啦,以上是本期内容,欢迎大佬们评论区指正,下次见~