Python------函数
Authors: 洋群满满
前言、
在实际开发中,如果有若干段代码的执行逻辑完全相同,那么阔以考虑将这些代码抽取成一个函数,这样不仅阔以提高代码的重要性,而且条理会更加的清晰,可靠性更高。
1.1、什么是函数
函数是组织好的,可重复使用的,用来实现单一的或者相关联功能的代码段,它能够提高应用的模块化和代码的重复利用率。python提供了很多内建函数,如print(),除此之外,我们还阔以自己创建函数,也就是自定义函数,接下来看一段代码:
print(' * ')
print(' *** ')
print('*****')
上述的代码中,使用了多个print()函数输出了一个三角形。如果需要在一个程序的不同位置输出这个图形,那么每次都是用这个print()函数输出的做法是不可取的。
为了提高编写效率以及代码的重用性,我们阔以把具有独特功能的代码块组织成一个小模块,这就是函数!
1.2、函数的定义和调用
1.2.1、定义函数
在python中,你阔以定义一个自己想要功能的函数,自定义函数的语法格式如下:
def 函数名(参数列表):
"函数_文档字符串"
函数体
return 表达式
基于上述格式,下面对函数定义的规则进行说明:
-
函数代码块已def开头,后面紧跟的是函数名和圆括号()、
-
函数名的命名规则跟变量的命名规则是一样的,即只能是字母刚、数字和下划线的任何组合,但不能以数字开头,并且不能和关键字重名、
-
函数的参数必须放在圆括号中、
-
函数的第一行语句阔以选择性的使用文档字符来存放函数说明、
-
函数内容以冒号起始,并且缩进、
-
return表达式结束函数,选择性的返回一个值给调用方,不带表达式的return相当于返回None、
接下来,定义一个能够完整打印信息的函数,如下所示:
# 接下来,定义一个能够完整打印信息的函数
def print_info():
print('-----------------------------')
print(' 人生可短,洋群满满 ')
print('-----------------------------')
1.2.2、调用函数
定义了函数之后,就相当于有了一段具有特定功能的代码,想要这些代码能够执行,需要调用函数。调用函数的方式很简单,通过“函数名()”即可完成成调用。
例如,调用1.2.1中的函数的代码如下:
# 定义完函数后,函数是不会自动执行的,需要调用它
print_info()
1.3、 函数的参数
1.3.1、 函数参数的传递
在介绍函数的参数之前,我们先来解决一个问题。现在要求定义一个函数,这个函数用于计算两个数的和,并把计算的结果打印出来。把上述的要求转换为代码,示例如下:
def add():
c = 11+22
print(c)
以上函数的功能是计算11和22的和。此时,无论调用这个函数多少次,得到的结果永远是一样的,而且只计算固定的两个数字的和,使得这个函数的局限性很大。
为了能让你定义的函数更加通用,即计算任意两个数字的和,阔以在定义函数的时候添加两个参数,让两个参数来接收传给函数的值。接下来,通过一个案例来演示下:
# 定义接收两个参数的函数
def add(a, b):
c = a+b
print(c)
在上面的例子中,定义了能接收两个参数的函数。其中,a为第一个参数,用于接收函数传递的第一个值;b为第二个参数,接收的是函数传递的第二个数值。这时,如果想调用add函数,则需要给函数的参数传递两个数值,代码如下:
# 调用带有参数的函数时,需要在小括号中传递数据
add(11, 22)
需要注意的是,如果函数定义了多个参数,那么在调用函数的时候,传递的数据要和定义的参数一一对应。
1.3.2、 默认参数
定义函数时,阔以给函数的参数设置默认值,这个参数就被称为默认参数。当调用函数的时候,由于默认参数在定义时已经被赋值,所以阔以直接忽略,而其它参数是必须要传入值的。如果默认参数没有传入值是,则使用默认的值;如果默认参数传入了值,则使用传入的新值替代。
接下来,演示如下:
# 接下来,定义一个能够完整打印信息的函数
def print_info(name, age = 25):
# 打印任何传入的字符串
print("Name:", name)
print("Age:", age)
print('*************')
# 调用函数
print_info(name='洋群满满')
print_info(name='洋群满满', age=22)
在上述的案例中,定义了一个带有两个参数的函数,其中name参数没有设置默认值,age作为默认参数设置了默认值。在后面的调用函数时,第一个由于只传入了name参数的值,所以程序会使用age参数的默认值;在第二个调用时,同时传入了两个参数的值,所以程序会用传给age参数的新值。
运行结果如下所示:
C:\Python\python.exe D:/Desktop/test/demo.py
Name: 洋群满满
Age: 25
*************
Name: 洋群满满
Age: 22
*************
Process finished with exit code 0
需要注意的是,带有默认值的参数一定要位于参数列表的最后面,否则程序会报错。例如,给print_info()函数添加一个参数sex,放在参数列表的最后面,则会报错如下:
C:\Python\python.exe D:/Desktop/test/demo.py
File "D:/Desktop/test/demo.py", line 19
def print_info(name, age = 25, sex):
^
SyntaxError: non-default argument follows default argument
Process finished with exit code 1
1.3.3、 不定长参数
通常在定义一个函数时, 若希望函数能够处理的参数个数能比当初定义的参数个数多,此时可以在函数中使用不定长参数。其基本语法的格式如下:
def 函数名([formal_args,] *args, **kwargs):
"函数_文档字符串"
函数体
return 表达式
在上述格式中,函数共有3个参数。其中formal_args为形参(也就是前面所用的参数,如a,b),*args和**kwargs为不定长参数。当调用函数的时候,函数传入的参数个数会优先匹配formal_args参数的格个数。如果传入的参数个数和formal_args参数的个数相同,不定长参数会返回控的元祖或字典;如果传入参数的个数比formal_args参数的个数多,阔以分为如下两种情况:
-
如果传入的参数没有指定名称,那么*args会以元祖的形式存放这些多余的参数;
-
如果传入的参数指定了名称,如m=1,那么**kwargs会以字典的形式存放这些被命名的参数,如{m:1}
为了让大家更好地理解,简单的示例演示下:
def test(a,b,*args):
print(a)
print(b)
print(args)
test(11, 22)
在上面的示例中,先定义了一个带有多个参数的test函。其中,args为不定长参数。在调用函数是,由于只传入了11和22这两个数,所以这两个数会从左向右依次匹配test函数定义时的参数a和b,此时,args参数没有接收到数据,所以为一个空的元祖。
程序运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
11
22
()
Process finished with exit code 0
如果在调用test函数时,传入了多个参数(这里指的是对于两个参数),情况下又是怎么样的呢?
下面看一段演示的代码:
def test(a,b,*args):
print(a)
print(b)
print(args)
test(11, 22, 33, 44, 55, 66, 77, 88, 99)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
11
22
(33, 44, 55, 66, 77, 88, 99)
Process finished with exit code 0
如果在参数列表的末尾使用**kwargs参数,演示代码如下:
def test(a,b,*args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11, 22, 33, 44, 55, 66, 77, 88, 99)
运行的结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
11
22
(33, 44, 55, 66, 77, 88, 99)
{}
Process finished with exit code 0
从两次的运行结果阔以看出,如果在调用test函数时传入多个数值,那么这些数会从左向右依次匹配函数test定义时参数。如果跟formal_args参数的个数匹配完,还有多余的参数,则这些多余的参数会组成一个元祖,和不定长参数args进行匹配。此时,kwargs参数没有接收到数据,所以为一个空字典。
那么思考一下,在调用函数时,在什么情况下传入数据会匹配参数kwargs呢?在上述的示例中,将调用函数的代码进行修改,修改后的代码如下所示:
def test(a,b,*args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11, 22, 33, 44, 55, 66, 77, n=88, m=99)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
11
22
(33, 44, 55, 66, 77)
{'n': 88, 'm': 99}
Process finished with exit code 0
从上述的运行结果阔以看出,如果参数是以键值对的形式传入的,则使用**kwargs参数来接收。
1.4、 函数的返回值
所谓的“返回值”,就是程序中的函数完成一件事情后,最后给调用者的结果。比如,定义了一个函数来获取“洋洋”与“群群”年龄的总和,一旦调用了这个函数,函数就会把得到总和的年龄返回给这个调用者,这个年龄总和就是函数的返回值。在python中,函数的返回值使用return语句来完成的。接下来,用一段示例代码演示一下:
def add(a, b):
c = a+b
return c
# 或者阔以这样写
def add(a, b):
return a+b
在上述的代码中,函数add中包含的return语句,意味着这个函数有一个返回值,其结果就是a加b的结果。
1.5、 函数的四种类型
根据有没有参数和返回值,函数大概阔以分为四种类型:
-
函数无参数,无返回值;
-
函数无参数,有返回值;
-
函数有参数,无返回值;
-
函数有参数,有返回值。
接下来,针对这四种类型的函数进行详细讲解。
1.5.1、 函数无参数,无返回值
无参数,无返回值的函数,既不能接收参数,也没有返回值。
接下来,通过一个打印提示的函数来演示这类函数的使用,如下所示:
def print_menu():
print('---------------------')
print(' 洋群满满 火锅菜单 ')
print(' 1、羊肉火锅')
print(' 2、牛肉火锅')
print(' 3、猪肉火锅')
print('---------------------')
print_menu()
运行结果如下所示:
C:\Python\python.exe D:/Desktop/test/demo.py
---------------------
洋群满满 火锅菜单
1、羊肉火锅
2、牛肉火锅
3、猪肉火锅
---------------------
Process finished with exit code 0
1.5.2、 函数无参数,有返回值
此类函数不能接受参数,但是阔以返回某个数据,一般情况下,采集数据时会用此类函数。接下来,实例演示下:
def get_temperature():
# 这里获取温度的一些过程
# 为了简单起见,先模拟返回一个数据即可
return 24
temperature = get_temperature()
print('当前的温度为:', temperature)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
当前的温度为: 24
Process finished with exit code 0
1.5.3、 函数有参数,无返回值
在实际开发中,有参数,无返回值类型的函数用的极少,这是因为函数作为功能模块,既然传入了参数,绝大多数情况下是希望使用返回值的。这里,大家对有参数,无返回值的函数有所了解即可,示例代码如下:
def test_add(num_one, num_two):
result = num_one + num_two
print('计算结果为', result)
test_add(11,22)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
计算结果为 33
Process finished with exit code 0
1.5.4、 函数有参数,有返回值
此类函数不仅能接收参数,还阔以返回某个数据,一般情况下,处理数据并需要结果的应用,阔以使用此类函数。接下来,通过一个哪里演示一下:
# 计算1~number的累积和
def calculate(number):
result = 0
i = 1
while i<=number:
result = result + i
i += 1
return result
result = calculate(100)
print('1~100的累积和为:',result)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
1~100的累积和为: 5050
Process finished with exit code 0
1.6、 函数案例-------名片管理器
名片管理器是一款生活实用类软件,用来协助管理手机中的所有名片。为了帮助大家在实际应用中学会实用四种类型函数,接下来,我们开发一个名片管理器。这个案例要求使用函数完成各种功能,你并且根据键盘的输入来选择对应的函数完成这些功能。
下面是名片管理器的菜单系统,如下所示:
--------------------------------
洋群满满 名片管理系统 v1.0
1、添加名片
2、删除名片
3、修改名片
4、名查询片
5、获取所有名片信息
6、退出系统
---------------------------------
如上所示,名片管理系统中共有六种功能,通过接收键盘输入的序号响应用户选择的功能。一旦用户输入了“6”, 就会退出系统。
创建一个工程,新建一个python文件,取名为“名片管理系统”, 具体实现步骤如下:
1.6.1、 输出名片管理器的菜单
定义输出菜单功能的函数。考虑到该函数只用来输出信息,并且输出的内容是固定不变的,所以定义一个无参数,无返回值的函数display_menu,具体的代码如下:
def display_menu():
print('-'*30)
print(' 洋群满满 名片管理系统 v1.0 ')
print(' 1、添加名片')
print(' 2、删除名片')
print(' 3、修改名片')
print(' 4、名查询片')
print(' 5、获取所有名片信息')
print(' 6、退出系统')
print('-'*30)
使用while循环不间断的输出菜单功能的信息。为了检测程序的可行性,阔以将while的判断条件改为“i<1”,
具体的实现代码如下:
i = 0
while i <1:
# 打印菜单
display_menu()
程序运行后,控制台一直不间断的输出菜单的信息。测试完毕后,使用Ctrl + F2停止程序。
1.6.2、获取用户输入的信息
菜单显示后, 用户需要根据提示输入要执行的序号。通过input()函数从键盘接收用户的选择,并且把选择的序号进行返回,所以定义一个无参数,有返回值的函数get_choice(),具体代码如下:
# 获取用户的选择
def get_choice():
selected_key = input('请输入您选择的序号:')
return int(selected_key)
在while循环打印菜单以后,调用了get_choice()函数来获取用户输入的信息,具体如下:
# 等待用户选择
key = get_choice()
运行结果如下:
C:\Python\python.exe D:/Desktop/test/aa.py
------------------------------
洋群满满 名片管理系统 v1.0
1、添加名片
2、删除名片
3、修改名片
4、名查询片
5、获取所有名片信息
6、退出系统
------------------------------
请入您选择的序号:
1.6.3、 通过获取序号,执行不同的功能
获取序号以后,根据序号的不同执行相应的操作。在while语句的末尾,使用if-else语句根据用户的选择的序号完成相应的功能,具体如下:
if key == 1:
pass
elif key == 2:
pass
elif key == 3:
pass
elif key == 4:
pass
elif key == 5:
pass
elif key == 6:
pass
else:
print('您的输入不符合要求或有误,请重新输入!!!')
接下来,在每个条件下来处理该序号对应的功能,这里只介绍“添加名片”和“查询名片”的功能。
-
添加名片
要想报存所有名片的信息,需要用到一个列表。在while语句前定义一个空的列表,具体如下:
name_list = []
用户选择了序号1,此时应该提示用户输入姓名,然后添加到上述的列表中,因此我们定义一个无参数,无返回值的函数,具体如下:
# 添加名片
def add_name():
new_name = input('请输入姓名:')
name_list.append(new_name)
接着在用户选择序号1的时候,调用上述函数实现的添加名片的功能,具体代码如下:
---省略其他代码---
if key == 1:
add_name()
elif key == 2:
---省略其他代码---
运行程序,控制台输出如图:
C:\Python\python.exe D:/Desktop/test/aa.py
------------------------------
洋群满满 名片管理系统 v1.0
1、添加名片
2、删除名片
3、修改名片
4、名查询片
5、获取所有名片信息
6、退出系统
------------------------------
请输入您选择的序号:1
请输入姓名:洋群满满
-
查询名片
用户选择了序号5,此时应该从列表中获取所有的姓名信息,按照固定的格式打印,因此我们定义了一个有参数,无返回值的函数print_all_info(),具体代码如下:
def print_all_info(temp_list):
print("="*30)
for info in temp_list:
print(info)
print("="*30)
紧接着在用户选择序号5的时候,调用上述方法实现产看所有名片的功能,具体如下:
---省略其他代码---
elif key == 5:
print_all_info(name_list)
elif key == 6:
---省略其他代码---
运行结果如下:
------------------------------
洋群满满 名片管理系统 v1.0
1、添加名片
2、删除名片
3、修改名片
4、名查询片
5、获取所有名片信息
6、退出系统
------------------------------
请输入您选择的序号:5
==============================
洋群满满
==============================
1.7、 函数的嵌套调用
在一个函数的调用另一个函数,这就是所谓的函数嵌套调用。接下来,我们通过一个示例来演示下:
def func_one():
print('------func one start------')
print('这里是func_one执行的代码')
print('------func one end------')
def func_two():
print('------func two start------')
func_one()
print('------func two end------')
func_two()
上述示例中,定义了两个函数func_one和func_two,其中func_two函数的内部调用了func_one函数。
具体运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
------func two start------
------func one start------
这里是func_one执行的代码
------func one end------
------func two end------
1.8、 变量作用域
1.8.1、 LEGB原则
Python中,程序的变量并不是在那个位置都是阔以访问的,访问的权限决定于这个变量在那里赋值的。我们先来看一段代码:
>>> a = 10
>>> def test():
... a = 20
... print('a的值是%d'%a)
...
>>> test()
a的值是20
上述的代码中有两个变量a,当在test函数中输出变量a的值时,为什么输出的是20,而不是10呢?其实,这就是因为变量作用域不同导致的。
变量的作用域决定了在那一部分程序阔以访问那个特定的变量名称。Python变量的作用域一共分为四种。分别是:
- L(Local): 函数内的区域,包括局部变量和参数
- E(Enclosing): 外面的嵌套函数区域,常见的是闭包函数的外层函数
- G(Global): 全局作用域
- B(Bulit-in): 内建作用域
Python中变量是采用 L -> E -> G -> B 的规则查找,即Python检索变量的时候,会优先在局部作用域中查找。如果没找到,便会去局部外的区域找( 例如闭包 ), 在找不到就会去全局变量作用域中找,最后再去内建作用域中找。
1.8.2、 全局变量与局部变量
变量的作用域始终是Python学习中一个必须理解掌握的环节,下面我们从局部变量和全局变量开始全面解析Python中变量的作用域。
所谓的局部变量,指的是定义在函数内部的变量。即定义在def函数内部的变量,只能在def函数内部使用,它与函数外具有相同名称的其他变量没有任何关系。不同的函数,阔以定义相同的局部名称,并且各个函数内的变量不会产生影响。示例代码如下:
>>> def test_one():
... number = 100
... print('test_one函数中的number值为:%d'%number)
...
>>> def test_two():
... number = 200
... print('test_two函数中的number值为:%d'%number)
...
>>> test_one()
test_one函数中的number值为:100
>>> test_two()
test_two函数中的number值为:200
局部变量只能在其声明的函数内部访问,而全局变量阔以在整个程序范围内部访问。全局变量是定义在函数外的变量,它拥有全局作用域。
接下来用一个案例来区分全局变量与局部变量,具体代码如下:
result = 100 # 全局变量
def sum(a, b):
result = a+b # 局部变量
print('函数内部的result的值为:%d' %result) # 这里的result值为局部变量
return result
# 调用sum函数
sum(100, 200)
print('函数外的变量result是全局变量,等于:%d' %result)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
函数内部的result的值为:300
函数外的变量result是全局变量,等于:100
Process finished with exit code 0
1.8.3、 global 和 nonlocal关键字
当内部作用域想修改外部作用域的变量时, 就要用到 global 和 nonlocal 关键字了。下面分别对 global 和 nonlocal 的作用进行介绍。
- global 关键字
global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也阔以不使用global关键字。具体代码如下:
>>> a = 100
>>> def test():
... a+=100
... print(a)
...
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test
UnboundLocalError: local variable 'a' referenced before assignment
上述的程序报错,提示“在赋值前引用了局部变量 a ”。但是,前面我们明明是阔以阔以在函数中访问全局变量啊?这里为什么会出错呢?啊哦!
这就是Python与其他语言的不同之处了, 在Python中,如果在函数内部对全局变量a进行修改,Python会把全局变量a当做局部变量, 而在进行“a+=100”之前,我们是没有声明局部变量a的, 因此,会出现上述的错误提示。
为了使全局变量生效,我们阔以在函数内使用global关键字进行声明,下面,我们对程序进行修改,代码入下:
>>> a = 100
>>> def test():
... global a
... a+=100
... print(a)
...
>>> test()
200
这下,程序不但没有报错,而且成功对全局变量a进行了修改。
-
nonlocal关键字
nonlocal 是在Python 3.0 中新增的关键字,Python 2.x 不提供支持。使用nonlocal关键字阔以在一个嵌套的函数中修改嵌套作用域中的变量。接下来,看一个例子:
>>> def func():
... count = 1
... def func_in():
... count = 2
... func_in()
... print(count)
...
>>> func()
1
上面的程序中,在嵌套的func_in函数中,对变量count进行了赋值,同样会创建一个新的变量,而非使用count=1 语句中的count,如果要修改嵌套作用域中的count,就要使用nonlocal关键字了,示例代码如下:
>>> def func():
... count = 1
... def func_in():
... nonlocal count
... count = 2
... func_in()
... print(count)
...
>>> func()
2
上述的代码中,在func_in()函数中使用了nonlocal关键字,就会告诉Python在func函数中使用嵌套作用域中的变量count,因此对变量count进行修改时,会直接影响到嵌套作用域中的count变量值,程序最后也就输出2了!
!!!注意!!!
使用global关键字修饰的变量之前是阔以不存在的,而使用nonlocal关键字修饰的变量在嵌套作用域中必须已经存在。
1.9 、 递归函数与匿名函数
1.9.1、 递归函数
通过前面的学习阔以知道,一个函数的内部是阔以调用其他函数的。如果在一个函数的内部调用了函数本身,那么这个函数我们就成为递归函数。
接下来,通过一个计算阶乘 n! = 1*2*…*n的例子来演示递归函数的使用,具体代码如下:
# 递归函数
def func(count):
if count ==1:
result = 1
else:
result = func(count-1)*count
return result
number = int(input('请输入一个正整数:'))
print("%d! ="%number, func(number))
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
请输入一个正整数:5
5! = 120
Process finished with exit code 0
1.9.2、 匿名函数
简单的来说,匿名函数就是没有名称的函数,也就是不再使用def语句定义的函数。如果要声明匿名函数,则需要使用lambda关键字,匿名函数的声明格式如下:
lambda [arg1[,arg2,...argn]]: experssion
上述格式中,”[arg1[,arg2,…argn]]“表示的函数的参数,”expression“表示的是函数的表达式。例如,下面声明的匿名函数。
add = lambda a, b: a+b
# 调用add函数
print("运行结果:", add(11, 22))
print("运行结果:", add(22, 22))
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
运行结果: 33
运行结果: 44
Process finished with exit code 0
需要注意的是,使用lambda声明的匿名函数能接收任意数量的参数,但只能返回一个表达式的值。匿名函数不能直接调用print()函数,这是因为lambda需要一个表达式。
在某些场景下,匿名函数非常有用。假设之前我们对两个数进行运算,如果希望声明的函数支持所有运算,阔以将匿名函数作为函数的参数进行传递。接下来,我们通过一个示例演示:
# 匿名函数-1
def func(a,b,c, aa):
print("a = %d"%a)
print("b = %d"%b)
print("c = %d"%c)
print("result = ", aa(a,b))
func(11,22,33, lambda x, y,i:x+y-i)
print('-'*20)
func(11,22,33, lambda x, y,i:x-y+i)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
a = 11
b = 22
c = 33
result = 0
--------------------
a = 11
b = 22
c = 33
result = 22
Process finished with exit code 0
除此之外,匿名函数还通常作为内置函数的参数来使用,接下来看一个例子:
# 匿名函数-2
students = [
{'name':'yangyang', 'age':'23'},
{'name':'qunqun', 'age':'24'},
{'name':'yangyangqunqun', 'age':'47'}
]
# 按name排序
students.sort(key=lambda x:x['name'])
print("按name排序后的结果为:", students)
# 按age排序
students.sort(key=lambda x:x['age'])
print("按name排序后的结果为:", students)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
按name排序后的结果为: [{'name': 'qunqun', 'age': '24'}, {'name': 'yangyang', 'age': '23'}, {'name': 'yangyangqunqun', 'age': '47'}]
按name排序后的结果为: [{'name': 'yangyang', 'age': '23'}, {'name': 'qunqun', 'age': '24'}, {'name': 'yangyangqunqun', 'age': '47'}]
Process finished with exit code 0
!!!注意!!!
与def定义的函数对比,lambda定义的函数有很多不同的地方。
- def定义的函数是有名称的,而lambda定义的函数没有函数名称,这是最明显的区别之一;
- lambda定义的函数通常会返回一个对象或者一个表达式,它不会将返回的结果赋值给一个变量,而def定义的函数就阔以;
- lambda定义的函数中只有一个表达式,函数体比def定义的函数简单很多,而def定义的函数的函数体是一个语句;
- lambda表达式的冒号后面只能有一个表达式,而def定义的函数则阔以有很多个;
- 像if或for等语句不能用于lambda定义的函数中,而def定义的函数阔以;
- lambda一般用来定义简单的函数,而def定义复杂的函数;
- lambda定义的函数不能共享给别的程序调用,而def定义的函数则阔以被调用。
1.10、 日期时间函数
Python 有很多处理日期和时间的方法,其中转换日期格式是最为常见的,Python提供了time和calendar模块用于格式化日期和时间。
1.10.1、 日期函数
在Python中,通常有如下几种方式表示时间:
- 时间戳
- 格式化的时间字符串
- 时间元祖(struct_time)
1.10.1.1、时间戳
通常来讲,时间戳表示的是从1970年1月1日00:00:00 开始按秒计算的偏移量。返回时间戳的函数主要有time(),clock()等。
接下来,通过一个案例来演示:
import time # 引入time模块
ticks = time.time()
print("当前的时间戳为:", ticks)
运行的结果为:
C:\Python\python.exe D:/Desktop/test/demo.py
当前的时间戳为: 1608983774.0507226
Process finished with exit code 0
1.10.1.2、格式化的时间字符串
我们阔以使用time模块的strftime函数来格式化日期,其定义的格式如下:
time.strftime(format[ ,t])
接下来,通过一个案例来演示strftime函数的使用,示例如下:
import time # 引入time模块
ticks = time.time()
print("当前的时间戳为:", ticks)
# 格式化成2020-12-26 20:05:49 形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# 格式化成Sat Dec 26 20:07:55 2020 形式
print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))
# 将格式字符串转换成时间戳
time_word = "Sat Dec 26 20:07:55 2020"
print(time.mktime(time.strptime(time_word, "%a %b %d %H:%M:%S %Y")))
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
当前的时间戳为: 1608984646.544159
2020-12-26 20:10:46
Sat Dec 26 20:10:46 2020
1608984475.0
Process finished with exit code 0
为了大家更全面的了解日期格式化,接下来,通过一张表来列举Python中的时间日期格式化符号,表如下:
格式化字符串 | 含义 |
---|---|
%y | 两位数的年份表示(00~99) |
%Y | 四位数的年份表示(000~9999) |
%m | 月份(01~12) |
%d | 月内中的一天 |
%H | 24小时制小时数(0~23) |
%I | 12小时制小时数(01~12) |
%M | 分钟数(00~59) |
%S | 秒(00~59) |
%a | 本地简化的星期名称 |
%A | 本地完整的星期名称 |
%b | 本地简化的月份名称 |
%B | 本地完整的月份名称 |
%c | 本地相应的日期表示和时间表示 |
%j | 年内的一天(001~336) |
%p | 本地的A.M.或者P.M.等价符 |
%U | 一年中的星期数(00~53),星期一为星期的开始 |
%w | 星期(0~6),星期日为星期的开始 |
%x | 本地相应的星期表示 |
%X | 本地相应的时间表示 |
%Z | 当前的时区的名称 |
%% | %本身 |
1.10.1.3、 时间元祖(struct_time)
返回struct_time的函数主要有gmtime()、localtime()和striptime(),struct_time元祖共有九个元素,我们通过一张表来列出元祖中的这些元素,如下表所示:
序号 | 字段 | 含义 | 取值范围 |
---|---|---|---|
0 | tm_year | 4位数的年份 | 例如:2020 |
1 | tm_mon | 表示月份 | 1~12 |
2 | tm_mday | 表示天数 | 1~31 |
3 | tm_hour | 表示小时数 | 0~23 |
4 | tm_min | 表示分钟数 | 0~59 |
5 | tm_sec | 表示秒数 | 0~61(60和61是闰秒) |
6 | tm_wday | 表示星期数 | 0~6(0是周一) |
7 | tm_yday | 表示一年中的第几天 | 1~366(儒略历) |
8 | tm_isdst | 决定是否为夏令时的标识符 | 允许的值为-1/0/1 |
另外,time模块还提供了很多其他的函数, 例如,sleep()函数用于推迟调用线程的运行,接下来,通过一张表来列举time模块的其他函数,具体如下表:
序号 | 函数名 | 含义 |
---|---|---|
1 | time.altzone | 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用 |
2 | time.asctime([tupletime]) | 接收时间元祖并返回一个可读的形式为“Tue Dec 11 18:07:14 2020”(2020年 12月 11日 周二 18点 07分 14秒)的24个字符的字符串 |
3 | time.clock() | 用于浮点数计算的秒数返回当前的CPU时间。用于衡量不同程序的耗时,比time.time()更有用 |
4 | time.ctime([secs]) | 作用相当于asctime(localtime(secs)),未提供参数相当于asctime() |
5 | time.gmtime([secs]) | 将一个时间戳转换为UTC时区(0时区)的struct_time,可选的参数sec表示从1970-1-1以来的秒数。其默认值为time.time(),函数返回time.struct_time类型的对象。注:t.tm_isdst始终为0 |
6 | time.localtime([secs]) | 类似gmtime(),作用是格式化时间戳为本地的时间。 如果sec参数未输入,则以当前时间为转换标准。 DST (Daylight Savings Time) flag (-1, 0 or 1) 是否是夏令时。 |
7 | time.mktime(tupletime) | 执行与gmtime(), localtime()相反的操作,它接收struct_time对象作为参数,返回用秒数来表示时间的浮点数。如果输入的值不是一个合法的时间,将触发 OverflowError 或 ValueError。 |
8 | time.sleep(secs) | 推迟调用线程的运行,可通过参数secs指秒数,表示进程挂起的时间。 |
9 | time.strftime(fmt[,tupletime]) | 接收以时间元组,并返回以可读字符串表示的当地时间,格式由参数 format 决定。 |
10 | time.strptime(str,fmt=’%a %b %d %H:%M:%S:%Y’) | 根据指定的格式把一个时间字符串解析为时间元组。 |
11 | time.time() | 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。 |
12 | time.tzset() | 根据环境变量TZ重新初始化时间相关设置。标准TZ环境变量格式:std offset [dst [offset [,start[/time], end[/time]]]] |
除此之外,time模块还包含了以下两个非常重要的属性具体如下表:
序号 | 名称 | 含义 |
---|---|---|
1 | time.timezone | 是当时时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<=0,大部分欧洲,亚洲,非洲) |
2 | time.tzname | 包含一对根据情况的不同而不的字符串,分别是带夏令时的本地时区名称和不带名称的 |
1.10.2、 日历函数
calendar模块中提供了非常多的方法来处理年历和月历。例如2020年12月份的日历具体代码实现如下:
import calendar
calendar_march = calendar.month(2020,12)
print("以下时2020年12月份的日历:")
print(calendar_march)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
以下时2020年12月份的日历:
December 2020
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
除此之外, calendar模块还提供了很多内置函数,具体如下表:
序号 | 名称 | 含义 |
---|---|---|
1 | calendar.calendar(year,w=2,I=1,c=6,m=3) | 以多行字符串形式返回一年的日历,w 每个单元格宽度,默认2,内部已做处理,最小宽度为2,l 每列换l行,默认为1,内部已做处理,至少换行1行,c 表示月与月之间的间隔宽度,默认为6,内部已做处理,最小宽度为2,m 表示将12个月分为m列 |
2 | calendar.firstweekday() | 返回一周的第一天,0是星期一,…,6为星期日 |
3 | calendar.isleap(year) | 判断指定是否是闰年,闰年为True,平年为False |
4 | calendar.ieapdays(y1,y2) | 返回y1 与y2 年份之间的闰年数量,y1 与y2 皆为年份。包括起始年,不包括结束年: |
5 | calendar.month(year,month,w=2,I=1) | 返回一个月的日历的多行文本字符串。year 指定年份,month 指定月份,w 每个单元格宽度,默认0,内部已做处理,最小宽度为2,l 每列换l行,默认为0,内部已做处理,至少换行1行 |
6 | calendar.monthcalendar(year,month) | 返回一个月中天数列表(不是当前月份的天数为0),按周划分,为一个二维数组。包括月份开始那周的所有日期和月份结束那周的所有日期 |
7 | calendar.monthrange(year, month) | 返回一个由一个月第一个天的星期与当前月的天数组成的元组 |
8 | calendar.prcal(year,w=2,I=1,c=6,m=3) | 打印一年的日历,w 每个单元格宽度,默认0,内部已做处理,最小宽度为2,l 每列换l行,默认为0,内部已做处理,至少换行1行,c 表示月与月之间的间隔宽度,默认为6,内部已做处理,最小宽度为2,m 表示将12个月分为m列 |
9 | calendar.prmonth(year,month,w=2,I=1) | 打印一个月的日历,theyear 指定年份,themonth 指定月份,w 每个单元格宽度,默认0,内部已做处理,最小宽度为2,l 每列换l行,默认为0,内部已做处理,至少换行1行 |
10 | calendar.setfirstweekday(firstweekday) | 指定一周的第一天,0是星期一,…,6为星期日 |
11 | calendar.timegm(tupletime) | 该函数将一个元组时间变成时间戳。 |
12 | calendar.weekday(year,month, day) | 获取指定日期为星期几 |
1.11、 随机数函数
Python中的random模块用于生成随机数,它提供了很多函数。接下来,针对常见的随机数函数进行讲解,具体如下:
1.11.1、 random.random()
返回0-1之间的浮点数N,范围为0<= N <=1.0。
接下来,通过一个示例来演示:
import random
# 生成第一个随机数
print('random():', random.random())
# 生成第二个随机数
print('random():', random.random())
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
random(): 0.9414705808484405
random(): 0.5730106704826693
Process finished with exit code 0
1.11.2、 random.uniform(a,b)
返回a与b之间的随机浮点数N,范围为[a,b]。 如果a的值小于b的值,则生成的随机浮点数N的取值范围为:a<= N <=b; 如果a的值大于b的值,则生成的随机浮点数N的取值范围为:b<= N <=a。示例如下:
import random
print('random():', random.uniform(50,100))
print('random():', random.uniform(100,50))
运行结果如下所示:
C:\Python\python.exe D:/Desktop/test/demo.py
random(): 94.65991375247847
random(): 60.57936076593128
Process finished with exit code 0
1.11.3、 random.randint(a,b)
返回一个随机整数N,N的取值范围为:a<= N <=b。 需要注意的是,a和b的取值必须是整数,并且a的值一定要小于b的值, 示例代码如下:
import random
# 生成随机数的范围为[12,20]
print('random.randint:', random.randint(12,20))
# 生成随机数的范围为[20,20], 结果永远为20
print('random.randint:', random.randint(12,20))
#print('random.randint:', random.randint(20,12))# 该语句是错误的,a的值必须小于b
结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
random.randint: 16
random.randint: 19
Process finished with exit code 0
1.11.4、 random.randrange([start], stop[,step])
返回指定递增基数集合中的一个随机数,基数默认值为1。其中,start
参数用于指定范围内的开始值,其包含在范围内;end
参数用于指定范围内的结束值,其不包含在范围内;step
表示递增的基数。
上述这些参数必须为整数。例如:random.randrange(10, 100, 2)相当于从[10,12,14…96,98]中获取一个随机数。
1.11.5、 random.choice(sequence)
从sequence中返回一个随机的元素。其中,sequence参数可以是列表、元祖或者字符串。示例代码如下:
import random
print('random.choice', random.choice('洋群满满'))
print('random.choice', random.choice(['洋','群满','满']))
print('random.choice', random.choice(('洋群', '满满')))
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
random.choice: 满
random.choice: 洋
random.choice: 洋群
Process finished with exit code 0
1.11.6、 random.shuffle(x,[,random])
用于将列表中的元素打乱顺序,俗称为洗牌
。示例代码如下:
import random
demo_list = ['python','洋群满满', 'java','C', 'javascript']
random.shuffle(demo_list)
print(demo_list)
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
['python', 'C', '洋群满满', 'java', 'javascript']
Process finished with exit code 0
1.11.7、 random.sample(sequence, k)
从指定序列中随机获取K个元素作为一个片段返回,sample函数不会修改原有序列。示例代码如下:
import random
num_list = [1,2,3,4,5,6,7,8,9,10]
slice = random.sample(num_list,5) # 从num_list中随机获取5个元素,作为一个片段返回
print(slice)
print(num_list) # 原有的序列顺序未改变
运行结果如下:
C:\Python\python.exe D:/Desktop/test/demo.py
[6, 3, 1, 5, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Process finished with exit code 0