Python的进阶之路
No.7、函数
函数是什么?
- 函数是组织好的,可重要使用的,用来实现单—,或相关联功能的代码段。
- 函数能提高应用的梩块性,和代码的重鲤利用率。
就像炒菜机可以封装好烹汪的各种步骤—样,函数也可以把我们要执行的代码放到—起,需要执行的时候,直接调用就可以。
实例: 平方函数, 输入变量 x 返回其平方值X^2:
def square(x):
s = x * x
return s
函数的定义:
a = 3
# 调用函数, 并打印出来
print square(a)
# 调用函数, 保存至变量b
b = square(a)
参数传递:
几种参数设定方法: 顺序传入、 关键词、 默认参数、 不定长参数
函数默认按照输入参数列表的顺序传入
x=1,y=2, z=3
# 多项式 s = 1 + 2*X + y^2 + Z*Y
def polynomial(x, y, z):
s = 1 + 2*x + y*y + z*y
return s
# 按位置输入
print polynomial(1, 2, 3)
>>>13
关键词传入:
- 直接在参数列表里设定关键词确定
# 多项式s = 1 + 2*X + y^2 + Z*Y
def polynomial(x, y, z):
s = 1 + 2*x + y*y + z*y
return s
print polynomial(x=1, y=2, z=3)
>>>13
默认参数:
- 输入的参数可以是事先设定好赋值,也就是默认值。 在调动函数的时候, 可以不输入参数, 函数内部会直接调用默认参数值。 例如默认z=3
def polynomial(x, y, z=3):
s = 1 + 2*x + y*y + z*y
return s
# 调用函数
polynomial(x=1, y=2)
>>>13
- 默认参数的默认值是可以修改的, 将上面的z 值传入设置为4,需要注意的是, 默认参数必须放到参数列表的末位.
# 调用函数,并输入修改的Z参数
polynomial(1, 2, z=4)
>>>15
不定长参数*args:
- 不定长参数是为了解决不确定需要传入参数个数的情况:
# *args
def print_keywords(x, *args):
for i in args:
print x + i
return
# 调用函数
print_keywords(1, 1, 2, 3)
>>>2
>>>3
>>>4
- 如果输入是一个list,那么可以用*list的方式传入
a = [1,2,3]
print_keywords(1, *a)
>>>2
>>>3
>>>4
匿名函数:
简化的函数定义方式:
polynomial= lambda x,y,z:1 + 2*x + y*y + z*y
polynomial(1, 2, 3)
>>>13
- lambda的主体是一个表达式, 而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的命名空间, 且不能访问自己参数列表之外或全局命名空间里的参数。
全局变量和局部变量:
- 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
- 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问:
Python的四种作用域:
L:(Local) 局部作用域
E:(Enclosing) 闭包函数外的函数中
G:(Global) 全局作用域
B:(Built-in) 内建作用域
total= 0 #这是一个全局变量
#可写函数说明
def sum(argl, arg2):
#返回2个参数的和
total= argl + arg2 # total在这里是局部变量.
print("函数佐是局部变量:",total)
return total
# 调用sum函数
sum(10, 20)
print("函数外是全局变量:",total)
- Python 中: 模块 (module) ,类(class)以及函数 (def、lambda)都会引入新的作用域,其它的代码块(如if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问。
局部变量:
在函数内部定义的普通变量只在函数内部起作用,称为局部变量。当函数执行结束后,局部变量自动删除,不可以再使用,如例所示。
def fun1():
x = 1 #局部变量
print('fun1()函数中的x为%d'%x)
def fun2():
x = 2 #局部变量
print('fun2()函数中的x为%d'%x)
fun1()
fun2()
#print(x)
>>>fun1()函数中的x为1
>>>fun2()函数中的x为2
全局变量:
如果需要在函数内部给一个定义在函数外的变量赋值,那么这个变量的作用域不能是局部的,而应该是全局的。能够同时作用于函数内外的变量称为全局变量,它通过global关键字来声明,如例所示。
x = 2 #全局变量
def fun():
global x #通过global关键字来声明
x += 1
print('x = %d'%x)
fun()
print(x)
此处需注意,如果不使用global声明,则在函数中访问的是局部变量
x = 2 #全局变量
def fun():
x = 3 #局部变量
print('x = %d'%x)
fun()
print(x)
此外,使用内置函数globals()与locals()可以查看局部变量与全局变量
x = 1 #全局变量
def fun():
x,y = 2,3 #局部变量
print(x,y)
global z #全局变量
z = 1
print(locals())
fun()
print(x)
print(globals())
在例中,函数globals()与locals()分别返回一个字典,通过打印字典中的元素,可以查看全局变量与局部变量。另外,在函数内部可以通过global关键字直接将一个变量声明为全局变量,即使在函数外没有定义,则该函数执行后,这个变量将成为全局变量,如本例中的变量z。
函数的嵌套调用:
Python语言允许在函数定义中出现函数调用,从而形成函数的嵌套调用,如例所示。
在例中,第6行在fun2()函数中调用fun1()函数,程序执行时会跳转到fun1()函数处去执行,执行完fun1()后,接着执行fun2()函数中剩余的代码,如图所示。
函数的递归调用:
- 在函数的嵌套调用中,一个函数除了可以调用其他函数外,还可以调用自身,这就是函数的递归调用。递归必须要有结束条件,否则会无限地递归(Python默认支持997次递归,多于这个次数将终止)。
在例中,第10行到第12行定义f()函数用于计算阶乘。当n ==0时,程序立即返回结果,这种简单情况称为结束条件。如果没有结束条件,就会出现无限递归。当n > 0时,就将这个原始问题分解成计算n –1阶乘的子问题,持续分解,直到问题达到结束条件为止,就将结果返回给调用者,然后调用者进行计算并将结果返回给它自己的调用者,该过程持续进行,直到结果返回原始调用者为止。原始问题就可以通过将f(n-1)的结果乘以n得到,这种调用过程就称为递归调用,如图所示。
常用的内建函数:
- eval()函数
eval()函数用于对动态表达式求值,其语法格式如下:
其中,source是动态表达式的字符串,globals和locals是求值时使用的上下文环境的全局变量和局部变量,如果不指定,则使用当前运行上下文。
接下来演示eval()函数的用法,如例所示。
x = 3
str = input('请输入包含x(x=3)的Python表达式:')
print(str,'的结果为',eval(str))
在例中,通过input()函数输入Python表达式,接着通过eval()函数求出该表达式的值。
- exec()函数
exec()函数用于动态语句的执行,其语法格式如下:
其中,source是动态语句的字符串,globals和locals是使用的上下文环境的全局变量和局部变量,如果不指定,则使用当前运行上下文。
接下来演示exec()函数的用法,如例所示。
str = input('请输入Python语句:')
exec(str)
在例中,通过input()函数输入Python语句,接着通过exec()函数执行该语句。
- compile()函数
compile()函数用于将一个字符串编译为字节代码,其语法格式如下:
其中,source为代码语句的字符串,filename为代码文件名称,如果不是从文件读取代码,则传递一些可辨认的值,mode为指定编译代码的种类,其值可以为’exec’、‘eval’、‘single’,剩余参数一般使用默认值。
接下来演示compile()函数的用法,如例所示。
str = input('请输入Python语句:')
co = compile(str,'','exec')
exec(co)
在例中,通过input()函数输入Python语句,接着通过compile()函数将字符串str转换为字节代码对象。
- map()函数
程序中经常需要对列表和其他序列中的每个元素进行同一个操作并把其结果集合起来,具体示例如下:
list1,list2=[1,2,3,4],[]
for i in list1:
list2.append(i + 10)
print(list2)
上述代码表示将list1中的每个元素加1并添加到list2中。该程序运行后,输出结果如下:
>>>[11,12,13,14]
实际上,Python提供了一个更方便的工具来完成此种操作,这就是map()函数,其语法格式如下:
其中,function为函数名,其余参数为序列,返回值为迭代器对象,通过list()函数可以将其转换为列表,也可以使用for循环进行遍历操作。
接下来演示map()函数的用法,如例所示。
list1 = [1,2,3,4]
func = lambda x : x + 10
list2 = list(map(sunc,list1)
print(list2)
在例中,map()函数对列表list1中的每个元素调用func函数并将返回结果组成一个可迭代对象,如图所示。
此外,map()函数还可以接受两个序列,具体示例如下:
list = list(map(lambda x,y:x+y,range(1,5),range(5,9)))
print(list)
>>>[6,8,10,12]
- filter()函数
filter()函数可以对指定序列进行过滤操作,其语法格式如下:
其中,function为函数名,它所引用的函数只能接受一个参数,并且返回值是布尔值,sequence为一个序列,filter()函数返回值为迭代器对象。
接下来演示filter()函数的用法,如例所示。
在例中,filter()函数对列表list中的每个元素调用func函数并返回使得func函数返回值为True的元素组成的可迭代对象,如图所示。
- zip()函数
zip()函数用于将一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的迭代对象,如例所示。
在例中,zip()函数将列表list1中第1个元素与列表list2中的1个元素组成一个元组,以此类推,最终返回由3个元组组成的迭代对象。
zip()参数可以接受任何类型的序列,同时也可以有两个以上的参数。但当传入参数的长度不同时,zip()函数以最短序列长度为准进行截取获得元组,具体示例如下:
该程序运行后,输出结果如下:
此外,在zip()函数中还可以使用运算符,如例所示。
在例中,第3行zip()函数中使用运算符相当于执行相反的操作。
在Python中,还有许多内建函数,当要用到某个函数时,只需在PyCharm编辑器中写出函数名,它就会自动提示函数的参数。例如,在编辑器中输入map后出现如图所示的提示。
此时在编辑器中接着输入(),则会提示函数的每个参数类型,如图所示。
Good bye!
PS:图片素材来源于网络。