第五章 - 函数(上)(5.1-5.7)
第五章 - 函数(上)(5.1-5.7)
5.1 什么是函数
函数是程序中重要的组成部分,那么到底什么是函数呢?
例如:当我们遇到一个人,我们想要介绍自己的时候,我们可以说:“我叫张三,我今年18岁,来自中国...”,但是当我们遇到另外一个人,又要自我介绍,又要说一遍。那为了解决这样的重复我们可以做一张名片,遇到人可以直接发名片呀!
print("我叫张三,我今年18岁,来自中国...")
print("我叫张三,我今年18岁,来自中国...")
print("我叫张三,我今年18岁,来自中国...")
# 我们使用函数来做成名片
def introduce():
print("我叫张三,我今年18岁,来自中国...")
# 这样遇到人就可以直接给名片,名片上就印着信息
introduce()
introduce()
以上,函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
5.2 函数的定义
Python 定义函数使用 def 关键字,一般格式如下:
def 函数名(参数列表):
函数体
当我们创建一个函数的同时我们要遵守函数的一些简单的规则:
-
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号
()
。 -
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
-
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
-
函数内容以冒号 : 起始,并且缩进。
-
return [表达式]
结束函数,选择性地返回一个值给调用方,不带表达式的return
相当于返回None
。
我们自定义一个简单的函数
# 自定义一个函数
def hello():
print('hello world!')
# 调用函数
hello()
# 前面我们学过pass语句,我们可以使用pass创建一个空的函数
def a():
pass
a()
5.3 函数的调用与返回值
5.3.1 函数调用
当定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,当我们想要调用一个函数时,可以使用 函数名()
方式调用。
# 定义一个函数
def func():
print("这是一个函数")
# 定义一个带有参数的函数
def name_func(name):
print("我叫:",name)
# 调用函数
func() # 这是一个函数
# 通过函数名调用传递参数
name_func('张三') # 我叫: 张三
5.3.2 函数返回值
一个函数就是封装一个功能,这个功能一般都会有一个最终结果的,return [表达式]
语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return
语句返回 None
。之前的例子都没有示范如何返回数值,以下实例演示了 return
语句的用法:
# 无返回值的函数
def func():
print("无返回值函数")
return
a = func()
print(a) # None
# 定义一个有返回值的函数
# return和返回值之间要有空格,可以返回任意数据类型的值
def name_func(name):
print('有返回值函数')
return '我的名字叫:%s'%name
ret_name = name_func('张三')
print(ret_name) #我的名字叫:张三
当然函数中使用 return
返回的内容不是只能返回字符串,也不是固定的数据类型,可以返回字符串、数字、列表、字典、元组、集合等形式的数据。
当然也不是只能返回一个内容,可以返回多个值。
# 定义一个多个返回值的函数
def name_func():
print('多个返回值返回值')
return 1,'我叫张三',[1,2,3],{'name':'张三'}
ret_name = name_func()
print(ret_name)
# (1, '我叫张三', [1, 2, 3], {'name': '张三'})
当返回多个值是,而接收只有一个时,会将所有值组成元组形式返回。
当然函数出现多个返回值并不是只能有一个接收,也可以多个接收
# 定义一个多个返回值的函数
def name_func():
print('多个返回值返回值')
return 1,'我叫张三',[1,2,3],{'name':'张三'}
a,b,c,d = name_func()
print(a,b,c,d)
# 1 我叫张三 [1, 2, 3] {'name': '张三'}
但是这里有多少返回值,就需要有多少变量接收,否则会报错。
总结:
-
函数中遇到
return
,函数结束,return
后面的内容也不会再执行。 -
return
返回值
- 如果return
后面没有返回的内容或者没有return
语句,返回的结果就是None
。
- 如果return
后面写了一个值,那么将这个值返回给调用者。
- 如果return
后面写了多个结果,Python会将所有返回的结果打包成个tuple
(元祖) 返回,当使用多个变量接收返回值,Python则将逐个返回。返回值与变量数量应该对应。
5.4 参数传递
5.4.1 参数
当我们在定义一个函数的时候,我们可以往函数内传递值,这个在定义时候 ()
内填的就是参数。
def 函数名(参数):
函数体
例如我们可以实现打印一个不同的名称:
# 定义一个带参数的函数
def func(name):
print('我的名字叫:%s'%name)
func('张三') # 我的名字叫:张三
func('李四') # 我的名字叫:李四
5.4.2 形参、实参、传参
1、 形参
当创建一个函数是,写在函数声明的位置 ()
内的变量叫形参,形式上的一个完整。表示这个函数需要xxx值。
2、实参
在函数调用的时候,调用者向函数传递的值,即实参,实际执行的时候给函数传递的信息,表示给函数xxx值。
3、传参
给函数传递信息的时候将实际参数交给形式参数的过程被称为传参。
# 定义一个带参数的函数
def func(name): # 这里的name就是形参,形式参数
print('我的名字叫:%s'%name)
func('张三') # 这里的'张三'就是实参,实际参数
# 我的名字叫:张三
func('李四') # 这里的'李四'就是实参,实际参数
# 我的名字叫:李四
# 函数调用打印出来的值则是形参的值,这里形参的值是我们调用时候传递的实参,这个过程叫做传参,即把参数传递过去。
5.4.3 参数的分类
在调用函数时候我们传递的参数类型有:
- 必需参数
- 关键字参数
- 默认参数
- 不定长参数
1、必需参数
必需参数,位置参数。当我们创建一个函数的时候,有一个或多个参数需要传递,这里我们在调用的时候必须要给函数一个参数,
# 这里有一个必需参数
def func(name):
print('我的名字叫:%s'%name)
# 调用的时候我们传递一个参数
func('张三')
# 我的名字叫:张三
# 当需要一个参数,而我们调用的时候并没有传递这个参数,则会报错
func() # 报错
我们定义一个函数,并不是只要一个参数,我们想要输出有姓名,性别,年龄等信息的文字,这个时候就需要多个参数。多个必需参数要按照正确的顺序传入函数。调用时的数量必须和声明时的一样。
# 定义一个多参数函数,需按照位置传递
def func(name,sex,age):
print('大家好!我叫:{},我是{}同学,今年{}岁'.format(name,sex,age))
func('张三','男',18)
# 大家好!我叫:张三,我是男同学,今年18岁
# 这个时候传递参数必须按照(name,sex,age)的顺序来传递参数。
# 当然不按照顺序也能传递,但是传递出来的结果就不一样的,这里就像给变量多元赋值一样。
func('男',18,'张三')
# 大家好!我叫:男,我是18同学,今年张三岁
# 但是这里必须要给三个参数,如果多了或者少了则会报错
func('张三','男')
# TypeError: func() missing 1 required positional argument: 'age'
func('张三','男',18,'张三')
# TypeError: func() takes 3 positional arguments but 4 were given
函数练习:
- 计算两个数之和
def sum(a,b):
c = a + b
return c
num_sum = sum(15,20)
print(num_sum) # 35
- 比较两个值大小返回最大值
def max(a,b):
if a > b:
c = a
else:
c = b
return c
max_num = max(8,5)
print(max_num)
def max(a,b):
if a > b:
return a
else:
return b
max_num = max(8,5)
print(max_num)
# 使用三目运算符
def max(a,b):
c = a if a > b else b
return c
max_num = max(8,5)
print(max_num)
2、关键字参数
函数在调用的时候,如果参数过多,使用位置参数就会容易出错,我们可以使用 key = value
的键值对形式来传递参数。称为关键字参数,这样我们就可以不按照位置来传递参数了。
def func(name,sex,age):
print('大家好!我叫:{},我是{}同学,今年{}岁'.format(name,sex,age))
func(name = '张三',sex = '男',age = 18)
# 大家好!我叫:张三,我是男同学,今年18岁
func(sex = '女',age = 18,name = '李四')
# 大家好!我叫:李四,我是女同学,今年18岁
当然我们可以位置参数与关键字参数混合使用
def func(name,sex,age):
print('大家好!我叫:{},我是{}同学,今年{}岁'.format(name,sex,age))
func('张三','男',age = 18)
# 大家好!我叫:张三,我是男同学,今年18岁
func('女',age = 18,name = '李四')
# 错误, 最开始使用了关键字参数, 那么后面的 微信的位置就串了, 容易出现混乱
但是这个地方要注意,位置参数要在关键字参数的前面,并且
使用的时候位置参数必须要对应,不能出现关键字重复传参的情况。不然会报错。
3、默认参数
默认参数指的是,当我们创建函数的时候我们使用 =
将参数赋值了一个默认的值,在调用函数时,如果没有传递参数,则会使用默认参数。
以下实例中如果没有传入 age 参数,则使用默认值:
def func(name,sex,age=18):
print('大家好!我叫:{},我是{}同学,今年{}岁'.format(name,sex,age))
func('张三','男')
# 大家好!我叫:张三,我是男同学,今年18岁
# 当我们传递参数时同样给了age一个值,这时就会使用传递的值
func('李四','女',20)
# 大家好!我叫:李四,我是女同学,今年20岁
默认参数的作用其实就是将改变较小的量,以及设定一个默认的值。
当我们在定义默认参数以及传参时,同样要按照先位置参数,关键字参数,默认参数。
4、不定长参数( *
与 **
的用法)
- *args
不定长参数又叫动态参数,当我们需要传递一个序列的时候,这个时候我们就不能使用上面的参数设置,否则会报错
def func(name):
print(name)
# 我们将一个姓名列表进行传参
name_list = ['张三','李四','王五']
func(name_list)
# ['张三', '李四', '王五']
# 这里如果我们分开传递
func('张三','李四','王五')
# 此时就会报错
为了解决这个问题,在Python中我们使用 *
来传递不定长参数。
def func(*name):
print(name)
func('张三','李四','王五')
# ('张三', '李四', '王五')
# 在不定长参数我们通常使用 *args 传递
def func2(*args):
print(args)
func2(1,2,3,4,5)
# (1, 2, 3, 4, 5)
这里需要注意:当我们传入不定长的参数时,Python会将这些参数全部以元组(tuple)形式传入。
- **kwargs
如果我们使用关键来传入不定长参数,这时候我们还能使用*args
吗?
def func(*args):
print(args)
func(name='张三',sex='男',age=18)
# TypeError: func() got an unexpected keyword argument 'name'
这个时候就会报错,那这种情况我们怎么来完成呢,就用到了 **kwargs
来进行传参接收。
def func(**kwargs):
print(kwargs)
func(name='张三',sex='男',age=18)
# {'name': '张三', 'sex': '男', 'age': 18}
**kwargs
是将以关键字传入的参数,全部以字典的形式进行传参。
那这里要讲一下,*args
是接收所有的位置参数; **kwargs
是接收所有的关键字参数。
*
的含义有:
- 函数中分为打散和聚合。
- 函数外可以处理剩余的元素。
聚合
上面我们在形参中使用的 *args
与 **kwargs
我们传入的值,Python会将这些值全部以元组和字典形式进行传参,这个过程 *
的作用就是聚合。
# 这里的*表示聚合
def func(*args):
print(args)
func('张三','李四','王二麻')
# ('张三', '李四', '王二麻')
# 这里的**表示聚合
def func(**kwargs):
print(kwargs)
func(name='张三',sex='男',age=18)
# {'name': '张三', 'sex': '男', 'age': 18}
打散
上面我们知道聚合,但是我们如果想输入多个不定长参数,s1 = 'zhangsan',l1 = [1, 2, 3, 4], tu1 = ('张三', '李四', '王二麻') 想要输出('z', 'h', 'a', 'n', 'g', 's', 'a', 'n', 1, 2, 3, 4, '张三', '李四', '王二麻')形式。
如果我们使用动态参数*args
def func(*args):
print(args)
s1 = 'zhangsan'
l1 = [1, 2, 3, 4]
tu1 = ('张三', '李四', '王二麻')
func(s1,l1,tu1)
# ('zhangsan', [1, 2, 3, 4], ('张三', '李四', '王二麻'))
你会发现他还是以一个整体传入的,那这个时候我们就需要把这些内容一个个拆开,然后合成一个进行传参。
lst = []
def func(*args):
for i in args:
for j in i:
lst.append(j)
print(lst)
s1 = 'zhangsan'
l1 = [1, 2, 3, 4]
tu1 = ('张三', '李四', '王二麻')
func(s1,l1,tu1)
# ['z', 'h', 'a', 'n', 'g', 's', 'a', 'n', 1, 2, 3, 4, '张三', '李四', '王二麻']
但是这样有点复杂,需要用到遍历,这个时候我们任然可以使用 *
来完成,这个时候就代表打散。
def func(*args):
print(args)
s1 = 'zhangsan'
l1 = [1, 2, 3, 4]
tu1 = ('张三', '李四', '王二麻')
# 打散
func(*s1,*l1,*tu1)
# ('z', 'h', 'a', 'n', 'g', 's', 'a', 'n', 1, 2, 3, 4, '张三', '李四', '王二麻')
注意:这个时候是以元组类型输出的,而上面是列表的方式,其实在这里,传入之前把参数全部打散,然后到形参*args
再进行聚合的时候是元组类型。
def func(**kwargs):
print(kwargs)
dit1 = {'name':'张三','sex':'男','age':18}
#dit2 = {'name':'李四','sex':'女','age':19}
# 这里由于字典的键不能重复,所以会出错
dit3 = {'hobby': '喝茶', 'eat': '海鲜'}
func(**dit1,**dit3)
# {'name': '张三', 'sex': '男', 'age': 18, 'hobby': '喝茶', 'eat': '海鲜'}
*
处理剩下的元素
*
除了在函数中可以这样打散,聚合外,函数外还可以灵活的运用:
# 之前讲过的分别赋值
a,b = (1,2)
print(a, b) # 1 2
# 其实还可以这么用:
a,*b = (1, 2, 3, 4,)
print(a, b) # 1 [2, 3, 4]
*rest,a,b = range(5)
print(rest, a, b) # [0, 1, 2] 3 4
print([1, 2, *[3, 4, 5]]) # [1, 2, 3, 4, 5]
5、 形参的顺序
到现在我们学到了位置参数,默认参数,关键字参数,动态参数*args,**kwargs。那我们在定义函数的时候是随便放吗?
def func(a,*args,c,**kwargs):
print(a)
print(args)
print(c)
print(kwargs)
func(1,2,3,4,name='zhang')
# TypeError: func() missing 1 required keyword-only argument: 'c'
这个地方显然是不行的,首先如果让我们去识别哪些是位置参数,那些是默认参数,那些是动态参数。
位置参数肯定是根据位置的,所有首先是位置的对应,这里就可以对应a的值为1,那么后面是*args取值,首先name='zhang'我们知道是**kwargs的传参,所以,在中间的Python都给了args。
所以在定义函数是先应该写 位置参数,*args,默认参数,关键字参数,**kwargs
这里要说一下默认参数与关键字参数,为什么在args之后,因为如果放在args之前,Python会认为,有一个值给了默认参数,所以默认参数的值会改变。
def func(name,age,sex='男',*args,**kwargs):
print('我叫{},今年{}岁,是{}生,喜欢{},还有{}'.format(name,age,sex,args,kwargs))
func('张三',18,'打篮球','羽毛球',eat='汉堡',study='python')
# 我叫张三,今年18岁,是打篮球生,喜欢('羽毛球',),还有{'eat': '汉堡', 'study': 'python'}
def func(name,age,*args,,sex='男'**kwargs):
print('我叫{},今年{}岁,是{}生,喜欢{},还有{}'.format(name,age,sex,args,kwargs))
func('张三',18,'打篮球','羽毛球',eat='汉堡',study='python')
# 我叫张三,今年18岁,是男生,喜欢('打篮球', '羽毛球'),还有{'eat': '汉堡', 'study':'python'}
如果把关键字放在args前面
def func(name,age,*args,sex='男',**kwargs):
print('我叫{},今年{}岁,是{}生,喜欢{},还有{}'.format(name,age,sex,args,kwargs))
func('张三',age=18,'打篮球','羽毛球',eat='汉堡',study='python')
# SyntaxError: positional argument follows keyword argument
这时候我们就知道关键字也应该放在args后面才行。
def func(name,*args,age,sex='男',**kwargs):
print('我叫{},今年{}岁,是{}生,喜欢{},还有{}'.format(name,age,sex,args,kwargs))
func('张三','打篮球','羽毛球',age=18,eat='汉堡',study='python')
# 我叫张三,今年18岁,是男生,喜欢('打篮球', '羽毛球'),还有{'eat': '汉堡', 'study': 'python'}
所以形参的顺序应该为(位置参数,*args,关键字参数,默认参数,**kwargs)
。
5.5 局部变量和全局变量
5.5.1 命名空间
- 命名空间一共分为三种:
- 全局命名空间
- 局部命名空间
- 内置命名空间
在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的。
也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间。随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空。
我们给这个‘存放名字与值的关系’的空间起了一个名字 ------- 命名空间
。
代码在运行开始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
在函数的运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间。
其实python还有一个空间叫做内置名称空间:内置名称空间存放的就是一些内置函数等拿来即用的特殊的变量:input,print,list等等,它们都是我们熟悉的,拿过来就可以用的方法。
总结:
- 全局命名空间 --> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间
- 局部命名空间 --> 在函数中声明的变量会放在局部命名空间
- 内置命名空间 --> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间
- 加载顺序
所谓的加载顺序,就是这三个空间加载到内存的先后顺序,也就是这个三个空间在内存中创建的先后顺序。
首先,在启动python解释器之后,即使没有创建任何的变量或者函数,还是会有一些函数直接可以用的比如abs(-1),max(1,3)等等,在启动Python解释器的时候,就已经导入到内存当中供我们使用,所以肯定是先加载内置名称空间,
然后就开始从文件的最上面向下一行一行执行,此时如果遇到了初始化变量,就会创建全局名称空间,将这些对应关系存放进去,然后遇到了函数执行时,在内存中临时开辟一个空间,加载函数中的一些变量等等。
所以这三个空间的加载顺序为:
内置命名空间(程序运行伊始加载) -->
全局命名空间(程序运行中:从上到下加载) -->
局部命名空间(程序运行中:调用时才加载。
- 取值顺序:
取值顺序就是引用一个变量,先从哪一个空间开始引用。这个有一个关键点:从哪个空间开始引用这个变量。我们分别举例说明:
# 如果你在全局名称空间引用一个变量,先从全局名称空间引用,全局名称空间如果没有,才会向内置名称空间引用。
input = 666
print(input) # 666
# 如果你在局部名称空间引用一个变量,先从局部名称空间引用,
# 局部名称空间如果没有,才会向全局名称空间引用,全局名称空间在没有,就会向内置名称空间引用。
input = 666
print(input) # 666
input = 666
def func():
input = 111
print(input) # 111
func()
所以空间的取值顺序与加载顺序是相反的,取值顺序满足的就近原则,从小范围到大范围一层一层的逐步引用。
在局部调用:局部命名空间->全局命名空间->内置命名空间
在全局调用:全局命名空间->内置命名空间
5.5.2 变量作用域
作用域就是作用范围, 按照生效范围来看分为全局作用域
和局部作用域
。
全局作用域(全局变量)
: 包含内置命名空间和全局命名空间,在整个文件的任何位置都可以使用(遵循 从上到下逐⾏执行)。
局部作用域(局部变量)
: 在函数内部可以使用。
作⽤域命名空间:
- 全局作用域: 全局命名空间 + 内置命名空间
- 局部作⽤域: 局部命名空间
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
- 内置函数globals(), locals()
这两个内置函数放在这里讲是在合适不过的,他们就直接可以反映作用域的内容,有助于我们理解作用域的范围。
globals(): 以字典的形式返回全局作用域所有的变量对应关系。
locals(): 以字典的形式返回当前作用域的变量的对应关系。
这里一个是全局作用域,一个是当前作用域,一定要分清楚,接下来,我们用代码验证:
# 在全局作用域下打印,则他们获取的都是全局作用域的所有的内容。
a = 2
b = 3
print(globals())
print(locals())
'''
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001806E50C0B8>,
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'D:/lnh.python/py project/teaching_show/day09~day15/function.py',
'__cached__': None, 'a': 2, 'b': 3}
'''
# 在局部作用域中打印。
a = 2
b = 3
def foo():
c = 3
print(globals()) # 和上面一样,还是全局作用域的内容
print(locals()) # {'c': 3}
foo()
- 关键字:global、nonlocal
- global
讲这个关键字之前,先给大家看一个现象:
a = 1
def func():
print(a)
func()
a = 1
def func():
a += 1 # 报错
func()
局部作用域对全局作用域的变量(此变量只能是不可变的数据类型)只能进行引用,而不能进行改变,只要改变就会报错,但是有些时候,我们程序中会遇到局部作用域去改变全局作用域的一些变量的需求,这就得用到关键字global
global第一个功能:在局部作用域中可以更改全局作用域的变量。
count = 1
def search():
global count
count = 2
search()
print(count)
# 利用global在局部作用域也可以声明一个全局变量。
def func():
global a
a = 3
func()
print(a)
所以global关键字有两个作用:
-
声明一个全局变量。
-
在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。
nonlocal
nonlocal是python3x新加的功能,与global用法差不多,就是在局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal,当然这个用的不是很多,了解即可。
def add_b():
b = 42
def do_global():
b = 10
print(b)
def dd_nonlocal():
nonlocal b
b = b + 20
print(b)
dd_nonlocal()
print(b)
do_global()
print(b)
add_b()
nonlocal的总结:
-
不能更改全局变量。
-
在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
5.6 匿名函数
Python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
lambda 函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
例如:我们想使用函数来计算两个数之和
def func(a,b):
return a+b
print(func(3,4))
那么接下来我们用匿名函数完成上面的需求:
func = lambda a,b: a+b
print(func(3, 4)) # 7
lambda 后面直接加形参,形参加多少都可以,只要用逗号隔开就行。
func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs
print(func(3, 4,c=666,name='alex')) # {'name': 'alex'}
# 所有类型的形参都可以加,但是一般使用匿名函数只是加位置参数,其他的用不到。
返回值在冒号之后设置,返回值和正常的函数一样,可以是任意数据类型。匿名函数不管多复杂,只能写一行,且逻辑结束后直接返回数据。
写匿名函数:接收一个可切片的数据,返回索引为0与2的对应的元素(元组形式)。
func = lambda x:(x[0],x[2])
print(func('afafasd'))
写匿名函数:接收两个int参数,将较大的数据返回。
func = lambda x,y: x if x > y else y
print(func(3,100))
5.7 函数的嵌套
就像列表中一样,一个列表中可以嵌套另外一个列表,函数中也可以嵌套一个函数。
# 例1:
def func1():
print('in func1')
print(3)
def func2():
print('in func2')
print(4)
func1()
print(1)
func2()
print(2)
# 这里按照顺序执行
# in func1
# 3
# 1
# in func2
# 4
# 2
# 例2:
def func1():
print('in func1')
print(3)
def func2():
print('in func2')
func1()
print(4)
# 先执行
print(1)
# 执行func2(),而后在func2中打印'in func2',
# 再执行func1,'in func1' 3
# 最后回到func2中打印4
func2()
print(2)
# 例3:
def fun2():
print(2)
def fun3():
print(6)
print(4)
fun3()
print(8)
print(3)
fun2()
print(5)