1. 函数定义
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
通俗理解:带名字的代码块,用于实现特定功能。Python 中使用def
关键字来定义函数
以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- 函数一般以return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None,如果没有return语句,则默认返回None。
- 函数遇到return就会终止,即return后面的代码将不会被执行。
函数的定义的格式:
def 函数名(参数):
pass
return 表达式
函数名命名规则: 字母、数字和下划线组成,和变量命名规则一致
return 后面可以返回任意表达式,但不能是赋值语句
2. 内置函数
通过观察,我们不难发现,函数有以下两个特点:
- 可以具体完成某个功能
- 可以重复使用
python(Python)中所谓的使用函数就是把你要处理的对象放到一个名字后面的括号里就可以了。简单的来说,函数就是这么使用,可以往里面塞东西就得到处理结果。这样的函数在Python中还有这些:
以最新的3.50版本为例,一共存在68个这样的函数,它们被统称为内建函数(Built-in Functions)。之所以被称之为内建函数,并不是因为还有“外建函数”这个概念,内建的意思是这些函数在3.50版本安装完成后你就可以使用它们,是“自带”的而已。千万不要为这些术语搞晕了头,随着往后学习,我们还能看见更多这样的术语,其实都只是很简单的概念,毕竟在一个专业领域内为了表达准确和高效往往会使用专业术语。
现在你并不必急着把这些函数是怎么用的都搞明白,其中一些内建函数很实用但是另外一些就不常用,比如涉及字符编码的函数ascii(),bin(),chr()等等,这些都是相对底层的编程设计中才会使用到的函数,在你深入到一定程度的时候才会派的上用场。
附上 Python官网中各个函数介绍的链接:https://docs.Python.org/3/library/functions.html,有兴趣深入了解的话可以看一眼。
3. 自定义函数
def test():
"""
这是一个没有方法体的函数,使用pass占位符代替代码块
:return:
"""
pass
def add(item):
""""
该函数有参数item,并使用return返回函数处理结果
:param item:
:return:
"""
return 5 + item
def show(item):
"""
该函数有方法体,但是没有指定返回值,返回None
:param item:
:return:
"""
5 + item
test()
print("调用add方法的返回值:",add(5))
print("调用show方法的返回值:",show(5))
运行结果如下:
调用add方法的返回值: 10
调用show方法的返回值: None
4. 函数调用
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
与大多数编程语言一样,通过函数名加一对小括号并正常传递参数,即可完成函数调用。需要注意的是,函数调用需要在函数申明之后,否则会触发异常,如下
def add(item):
print("在add中调用sub:",sub(item))
return 5 + item
try:
sub(5)
except Exception as e:
print("在函数申明前调用,触发异常:",e)
def sub(item):
return 10 - item
print("调用add方法:",add(5))
为什么在第6行调用了sub报错,而第2行调用sub就能正常执行了呢?原因是代码是从上往下解析的,调用sub时,sub方法还未创建。sub方法是在第10行创建的,在第13行调用add方法时,sub方法已经创建完成,因此得到正确的结果,运行结果如下:
在函数申明前调用,触发异常: name 'sub' is not defined
在add中调用sub: 5
调用add方法: 10
5.函数的参数
Python函数的参数具有灵活性,其定义的方法可以接受各种形式的参数,也可以简化函数调用方法的代码。
5.1 形式参数和实际参数
- 形式参数:函数定义时候的参数
- 实际参数:函数调用时候的参数
5.2 位置参数
- 位置参数:形式参数和实际参数要一一按照顺序对应,不多不少,位置一样。
如下,func1函数具有1个位置参数,func2函数具有2个位置参数。在对函数进行调用的时候,有几个位置参数就需要传递几个参数,否则会触发异常。并且,传入参数与函数参数列表是一一对应的,如第13行,a等于10,b等于20。
def func1(a):
print("输出位置参数a的值:",a)
return a
def func2(a,b):
print("输出位置参数a:%a,b:%s"%(a,b))
return a+b
print("函数调用func1(10):",func1(10))
print("")
print("函数调用func2(10,20):",func2(10,20))
运行结果如下:
输出位置参数a的值: 10
函数调用func1(10): 10
输出位置参数a:10,b:20
函数调用func2(10,20): 30
关于函数的参数传递,我们需要注意如下几点:
- 调用函数传递的参数个数一定要和函数定义的参数个数一致,否则会报错;
- 注意函数体里面参数的类型,要输入正确的参数类型,否则会报错。
5.3 函数的默认参数
- 在函数定义的时候,给形式参数一个默认值,即为默认参数;
- 在函数定义时,如果有默认值,在调用时如果传入了实际参数,那么默认参数不会生效,如果没有传入实际参数,默认参数会生效。
5.4 位置参数与默认参数
一个函数有的时候不仅有位置参数,还会有默认参数,如果这两种参数同时存在的时候,就一定要把默认参数放在位置参数的后面,否则会报错!!
5.5 可选参数
如下,可选参数是指带有默认值的参数,在对该函数进行调用的时候,可以不必显示传递该函数。当不传递默认函数,函数将使用默认值,如第6行;若传递默认函数,函数将使用传入的值,如第8行。可选参数常用于修改一个现有的函数,避免该函数在其他调用的地方出错。
def func2(a,b=5):
print("输出位置参数a:%a,可选参数b:%s"%(a,b))
return a+b
print("调用时传递1个参数func2(1):",func2(1))
print("")
print("调用时传递2个参数func2(1,2):",func2(1,2))
运行结果如下:
输出位置参数a:1,可选参数b:5
调用时传递1个参数func2(1): 6
输出位置参数a:1,可选参数b:2
调用时传递2个参数func2(1,2): 3
5.6 可变参数与关键字参数
- 作用:是相对于位置参数讲的,可以提高函数调用时候的可读性,更加容易理解实际参数的意义;
- 关键字的名字===形式参数;
- 关键字参数区别位置参数,可以不按照顺序进行调用,可以交换顺序;
- 关键字参数也要放到位置参数的后面。
可变参数是指在传递参数时,可以传递任意个数的参数;关键字参数是指可以传递任意个包含名字的参数。如下,func1函数定义的可变参数,适用于传递列表、元组,使用" * “;func2函数适用于传递字典,字典中的键名即为参数名称,使用” ** ",这一点和参数解包的逻辑是一样的。
def func1(*args):
count=0
for i in args:
count=count + i
return count
def func2(**kwargs):
tmp_list=[]
for k,v in kwargs.items():
tmp_list.append("key:%s value:%s"%(k,v))
return tmp_list
data = [1,2,3,4,5]
print("传递可变参数:",func1(*data))
data=(1,3,5)
print("传递可变参数:",func1(*data))
dic={"key1":1,"key2":2}
print("传递关键字参数:",func2(**dic))
运行结果如下:
传递可变参数: 15
传递可变参数: 9
传递关键字参数: ['key:key1 value:1', 'key:key2 value:2']
以上是对于已有列表、元组、字典对象进行传递,还可以不使用" * ",直接传递,如下
print("传递可变参数:",func1(1,2,3,4,5))
print("传递可变参数:",func1(1,3,5))
print("传递关键字参数:",func2(key1=1,key2=2))
如下,第2行参数列表中有一个" * “,之后的参数就是关键字参数,其名称是” c " 和" d “,调用方式如第12行所示。当” * “后面紧接着名称,如第7行,则不必单独写一个” * "。
def func1(a,b=5,*,c,d):
print("输出位置参数a:%a,可选参数b:%s,\n命名关键词参数c:%s,命名关键字参数d:%s"%(a,b,c,d))
def func2(a,b=5,*args,c,d):
print("输出位置参数a:%a,可选参数b:%s,\n命名关键词参数c:%s,命名关键字参数d:%s"%(a,b,c,d))
func1(10,c=11,d=12)
print("")
func2(10,c=11,d=12)
运行结果如下:
输出位置参数a:10,可选参数b:5,
命名关键词参数c:11,命名关键字参数d:12
输出位置参数a:10,可选参数b:5,
命名关键词参数c:11,命名关键字参数d:12
5.7 不定长参数
不定长参数包括位置不定长参数和关键字不定长参数:
- *args:位置不定长参数;
- *kwargs:关键字不定长参数
(1)位置不定长参数:*args
- *args:在函数内部的表现形式:names是一个元组
- *args:可以接收从函数调用的时候多余的位置参数
- *args:加在其他位置参数的后面
(2)关键字不定长参数:*kwargs
上面我们讲了不定长位置参数,这一节我们来掌握下带有关键字的不定长参数。它与普通的不定长参数的区别就是带有关键字,且必须指定关键字,否则识别不了。
6. 函数的返回值
Python中的函数可以使用return返回数据,也可以不用return返回,则默认返回" None "。在Python中,所有事物都被当做对象,函数也是一个对象,因此函数的返回值可以是另一个函数。
6.1 返回零到多个值
如下,func1函数,没有使用return返回数据,因此默认返回值为" None "。func2函数有多个返回值,默认情况下,这些返回值将构成一个元组进行返回,因此在倒数第5行,变量a是一个元组类型。func2函数返回了两个值,因此在倒数第2行定义了两个变量,分别接收这两个值,这成为返回值解包。
def func1():
print("调用func1函数:")
def func2(item1,item2):
return item1 +5,item2 +6
a=func1()
print("func1返回值a的值为:",a,end="\n\n")
p1={"item1":10,"item2":11}
print("调用func2函数:")
a=func2(**p1)
print("func2返回值a的类型为:",type(a))
print("func2返回值a的值为:",a)
a,b=func2(**p1)
print("func2返回值解包,a是:%s,b是:%s"%(a,b))
运行结果如下:
调用func1函数:
func1返回值a的值为: None
调用func2函数:
func2返回值a的类型为: <class 'tuple'>
func2返回值a的值为: (15, 17)
func2返回值解包,a是:15,b是:17
6.2 返回函数
如下,在fun1函数中返回了fun2的函数名称。那么在第7行,变量fun就是一个函数对象,因此输出fun的类型为<class’function’>。既然fun是函数,那么在fun后面加一对小括号就能对其进行调用,如第9行
def fun1():
def fun2():
return 10
return fun2
fun=fun1()
print("fun1返回值类型:",type(fun))
result=fun()
print("fun()调用结果为:",result)
运行结果如下:
fun1返回值类型: <class 'function'>
fun()调用结果为: 10
7. 全局变量和局部变量
1、定义
- 局部变量是在函数内部声明的变量,只能在该函数调用它,如果试图在超出范围的地方调用,程序就会报错;
- 全局变量是在整个整个py文件中定义的变量,全局范围内都可以访问。
2、局部变量和全局变量需要注意的几个点
- 全局作用域能获取局部变量吗??? 不能!!!
- 全局作用域能修改局部变量吗??不能!!!
- 局部作用域能获取全局变量吗??能!!!
- 局部变量能修改全局变量吗??不能!!!
3、局部作用域修改全局变量的方法
- global 关键字是声明全局变量的关键字
全局变量和局部变量是一个相对的概念,在函数内部的变量,称为局部变量;在该函数外的变量,称为全局变量。若是需要将变量对所有函数可见,则需要加global关键字进行修饰。如下,global将var1、var2、var3都变成了全局变量,因此在fun方法外,还能正常访问,访问变量var4,程序则会触发异常。
def fun():
global var1,var2,var3
var1=100
var2=200
var3=300
var4=400
print("fun中的局部变量var1:%s,var2:%s,var3:%s,var4:%s"%(var1,var2,var3,var4))
fun()
print("全局变量var1:%s,var2:%s,var3:%s"%(var1,var2,var3))
try:
print("输出变量var4:%s"%(var4))
except Exception as e:
print("异常信息:",e)
运行结果如下:
fun中的局部变量var1:100,var2:200,var3:300,var4:400
全局变量var1:100,var2:200,var3:300
异常信息: name 'var4' is not defined
注意,在Python中,使用global方法,可以获取当前程序内部所有的全局变量