一、实验目的
- 函数的定义
- 局部/全局变量的概念
- 默认参数,关键字参数及强制关键字参数
- 文档字符串的使用
- 高阶函数,map() 函数
二、知识要点
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。我们已经知道Python提供了许多内建函数,比如print()。但我们也可以自己创建函数,这被叫做用户自定义函数。
1.定义一个函数
- 流程:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
- 语法格式:
1 | #定义 函数名 (参数): |
2.调用函数
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
3.对象
对象类型 | |||
---|---|---|---|
可更改对象 | Strings(字符串) | tuples(元组) | numbers(数字 |
不可更改对象 | list(列表) | dict(字典) |
下面的例子将解析可更改对象与不可更改对象的区别: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
30def change(string_2, tuples_2, int_2, float_2, list_2, dict_2, set_2):
print("已收到传入参数,传入值为:", string_2, tuples_2, int_2, float_2, list_2, dict_2, set_2)
string_2 = "newstring"
del tuples_2
int_2 = 3
float_2 = 2.0
list_2[0] = "newlist1"
dict_2['dict1'] = "newfirst"
del set_2
print("已修改传入参数,目前的属性值为:", string_2, int_2, float_2, list_2, dict_2)
try:
print(tuples_2)
except Exception:
print("tumples_2已删除")
try:
print(set_2)
except Exception:
print("set_2已删除")
return
string_1 = "string" # 字符串对象
tuples_1 = ("tuples1", "tuples2", 3) # 元组对象
int_1 = 2 # 整型对象
float_1 = 1.0 # 浮点型对象
list_1 = ["list1", "list2", 3] # 列表对象
dict_1 = {"dict1": "first", "dict2": 2} # 字典对象
set_1 = {"set1", "set2", 3} # 集合对象
change(string_1, tuples_1, int_1, float_1, list_1, dict_1, set_1)
print("返回值为:\n", string_1, tuples_1, int_1, float_1, list_1, dict_1, set_1)
我们用一个表格来解析一下整个过程:
变量 | 输入 | 传入函数 | 修改之后 | 输出 |
---|---|---|---|---|
string | “string” | “string” | “newstring” | “string” |
tuples | (“tuples1”,”tuples2”) | (“tuples1”,”tuples2”) | delete | (‘tuples1’, ‘tuples2’, 3) |
int | 2 | 2 | 3 | 2 |
float | 1.0 | 1.0 | 2.0 | 1.0 |
list | [“list1”, “list2”, 3] | [“list1”, “list2”, 3] | [‘newlist1’, ‘list2’, 3] | [‘newlist1’, ‘list2’, 3] |
dict | {“dict1”: “first”, “dict2”: 2} | {“dict1”: “first”, “dict2”: 2} | {‘dict1’: ‘newfirst’, ‘dict2’: 2} | {‘dict1’: ‘newfirst’, ‘dict2’: 2} |
set | {“set1”, “set2”, 3} | {“set1”, “set2”, 3} | delete | {3, ‘set1’, ‘set2’} |
可以看到,只有属性为列表对象list
,字典对象dict
可以在函数中修改,而字符串对象string
,整型对象int
,浮点型对象float
,元组对象tuples
,集合对象set
是无法在函数中修改的。
4.参数
- 必备参数:必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。例如:
1 | def must(str): |
该代码会输出未传入参数异常
。
- 关键字参数:关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。例如:
1 | def keyword_1(name_1, age_1): |
该代码会输出name_1 is zhe,age_1 is 10
,关键字参数顺序不重要。
- 默认参数:调用函数时,默认参数的值如果没有传入,则被认为是默认值。例如:
1 | def default(name, age=35): |
输出为:1
2name is zhang,age is 50
name is zhe,age is 35
- 不定长参数:处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下:
1 | def functionname([formal_args,] *var_args_tuple ): |
加了星号(*)的变量名会存放所有未命名的变量参数。不定长参数实例如下:1
2
3
4
5
6
7
8
9def nolenth_n(num_1, *num):
print("输入的常量是:", num_1)
for x in num:
print("可变参数:", x)
return
nolenth_n(10)
nolenth_n(10, 20, 30, 40)
输出:1
2
3
4
5输入的常量是: 10
输入的常量是: 10
可变参数: 20
可变参数: 30
可变参数: 40
在可变参数后定义的参数必须通过关键词传入:
例如:1
2
3
4
5
6
7
8
9
10
11
12def Force_key(name, *home, age):
print("传入name为{},age为{}".format(name, age))
return
try:
Force_key(name="zhang")
except Exception:
print("传入异常")
try:
Force_key("zhang",age=16)
except Exception:
print("传入异常")
输出为:1
2传入异常
传入name为zhang,age为16
5.匿名函数
python 使用 lambda 来创建匿名函数。lambda只是一个表达式,函数体比def简单很多。lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
匿名函数语法:1
lambda [arg1 [,arg2,.....argn]]:expression
例如:1
2
3
4
5sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print("相加后的值为 : ", sum(10, 20))
print("相加后的值为 : ", sum(20, 20))
输出为:1
2相加后的值为 : 30
相加后的值为 : 40
6.return
语句
return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值,下例便告诉你怎么做:1
2
3
4
5
6
7
8
9def sum(arg1, arg2):
# 返回2个参数的和."
total = arg1 + arg2
print("函数内 : ", total)
return total
# 调用sum函数
total = sum(10, 20)
该程序输出函数内 : 30
7.全局变量与局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。下面的例子有助于理解这两个概念:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20a = 9
def global_1():
try:
print(a)
a = 100
except Exception:
print("变量a误作局部变量")
def global_2():
try:
global a
print(a)
a = 100
except Exception:
print("变量a误作局部变量")
print("Before the function call ", a)
print("inside change function")
global_1()
print("After the function global_1() call ", a)
global_2()
print("After the function global_2() call ", a)
输出:1
2
3
4
5
6Before the function call 9
inside change function
变量a误作局部变量
After the function global_1() call 9
9
After the function global_2() call 100
当函数中只要用到了变量 a
,并且 a
出现在表达式等于号的前面,就会被当作局部变量。当执行到 print(a)
的时候会报错,因为 a
作为函数局部变量是在print(a)
之后才定义的。而当使用 global
关键字,对函数中的 a
标志为全局变量,让函数内部使用全局变量的a
,程序中就没有问题了。
8.文档字符串
DocStrings 文档字符串是一个重要工具,用于解释文档程序,帮助你的程序文档更加简单易懂。我们可以在函数体的第一行使用一对三个单引号'''
或者一对三个双引号"""
来定义文档字符串。你可以使用 __doc__
(注意双下划线)调用函数中的文档字符串属性。例如:
1 | def function(): |
输出为say something here!
9.高阶函数
高阶函数(Higher-order function)或仿函数(functor)是可以接受函数作为参数的函数:
- 使用一个或多个函数作为参数
- 返回另一个函数作为输出
例如:1
2
3
4
5
6
7
8def high(l):
return [i.upper() for i in l]
# 创建高阶函数,接受一个函数和一个列表作为参数
def test(h, l):
return h(l)
l = ['python', 'Linux', 'Git']
print(test(high, l))
输出为['PYTHON', 'LINUX', 'GIT']
三、实验内容
1.定义一个函数用于实现求和运算
- 代码:
1 | def sum_my(a, b): |
2.在代码中调用求和方法
- 代码:
1 | def sum_my(a, b): |
- 结果:
1 | Please enter an number:2 |
3.重要的高阶函数
3.1 map()
map
是一个在 Python 里非常有用的高阶函数。它接受一个函数和一个序列(迭代器)作为输入,然后对序列(迭代器)的每一个值应用这个函数,返回一个序列(迭代器),其包含应用函数后的结果。举例:1
2
3
4
5lst = [1, 2, 3, 4, 5]
def square(num):
return num * num
print(list(map(square, lst)))
输出为[1, 4, 9, 16, 25]
- map函数用来将序列中的值处理再依次返回至列表内;
- 第一个参数func为函数,实现函数映射的功能,第二个参数为可迭代对象;
- map函数的返回值为一个迭代器对象map;
3.2 sorted()
1 | # 反向排序 |
输出:1
2['g', 'f', 'e', 'd', 'c', 'b', 'a']
[[1, 2], [8, 3], [5, 6], [2, 8], [3, 10]]
- sorted是Python提供的功能强大的排序函数,满足字符、数字等排序要求;
- 函数的第一个参数为可迭代对象,第二个参数key作为排序的规则(指定按什么排序),第三个参数表明是否反向;
- sorted函数的返回结果是列表类型;
3.3 filter()
1 | # 过滤 |
输出:1
2
31
10
20
- filter函数也是接收一个函数和一个序列的高阶函数,其主要功能是过滤;
- 第一个参数是一个函数,第二个参数是可迭代对象;
- filter函数的返回值是迭代器对象filter;
四、实验结果
无