定义:
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
目的:
函数能提高应用的模块性,和代码的重复利用率。
分类:
内建函数、自定义函数。
你已经知道Python提供了许多内建函数,比如print()。
但你也可以自己创建函数,这被叫做用户自定义函数。
举例:
#!/usr/bin/python3
#计算面积函数(自定义)
defarea(width, height):return width *height#打印问候(自定义)
defprint_welcome(name):print("Welcome", name)
print_welcome("Runoob")
w= 4h= 5
#打印(内建函数)
print("width =", w, "height =", h, "area =", area(w, h))
参数传递
在 python 中,类型属于对象,变量是没有类型的:
#!/usr/bin/python3
#可写函数说明
defprintinfo( name, age ):"打印任何传入的字符串"
print ("名字:", name);print ("年龄:", age);return;#调用printinfo函数
printinfo( age=50, name="runoob" );
以上实例输出结果:
名字: runoob
年龄:50
默认参数
调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
#!/usr/bin/python3
#可写函数说明
def printinfo( name, age = 35):"打印任何传入的字符串"
print ("名字:", name);print ("年龄:", age);return;#调用printinfo函数
printinfo( age=50, name="runoob");print ("------------------------")
printinfo( name="runoob" );
输出结果:
名字: runoob
年龄:50
------------------------名字: runoob
年龄:35
不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下
加了星号(*)的变量名会存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。如下实例:
#!/usr/bin/python3
#可写函数说明
def printinfo( arg1, *vartuple ):"打印任何传入的参数"
print ("输出:")print(arg1)for var invartuple:print(var)return;#调用printinfo 函数
printinfo( 10);
printinfo(70, 60, 50 );
以上实例输出结果:
输出:10输出:70
60
50
变量作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
x = int(2.9) #内建作用域 B
g_count= 0 #全局作用域 G
defouter():
o_count= 1 #闭包函数外的函数中 E
definner():
i_count= 2 #局部作用域 L
Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:
>>> ifTrue:
... msg= 'I am from Runoob'...>>>msg'I am from Runoob'
>>>
实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。
如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:
>>> deftest():
... msg_inner= 'I am from Runoob'...>>>msg_inner
Traceback (most recent call last):
File"", line 1, in NameError: name'msg_inner' is notdefined>>>
从报错的信息上看,说明了 msg_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。
全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
#!/usr/bin/python3
total= 0; #这是一个全局变量
total2 = 0; #这是一个全局变量#可写函数说明
defsum( arg1, arg2 ):#返回2个参数的和."
total = arg1 + arg2; #total在这里是局部变量.
print ("函数内是局部变量 :", total)
global total2
total2= arg1 + arg2; #total在这里是全局变量.
returntotal;#调用sum函数
sum( 10, 20);print ("函数外是全局变量 :", total)print ("函数外是全局变量2 :", total2)
以上实例输出结果:
函数内是局部变量 : 30函数外是全局变量 : 0
函数外是全局变量2 : 30
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:
#!/usr/bin/python3
defouter():
num= 10
definner():
nonlocal num#nonlocal关键字声明
num = 100
print(num)
inner()print(num)
outer()
以上实例输出结果:
100
100
另外有一种特殊情况,假设下面这段代码被运行:
#!/usr/bin/python3
a= 10
deftest():
a= a + 1
print(a)
test()
以上程序执行,报错信息如下:
Traceback (most recent call last):
File"test.py", line 7, in test()
File"test.py", line 5, intest
a= a + 1UnboundLocalError: local variable'a' referenced before assignment
错误信息为局部作用域引用错误,因为 test 函数中的 a 使用的是局部,未定义,无法修改。
其他实际问题:
1、默认参数必须放在最后面,否则会报:
SyntaxError: non-default argument follows default argument
#可写函数说明
def printinfo( age=35,name): #默认参数不在最后,会报错
"打印任何传入的字符串"
print("名字:", name);print("年龄:", age);return;
2、把N个关键字参数转化为字典:
>>> def func(country,province,**kwargs):
...print(country,province,kwargs)
...>>> func("China","Sichuan",city = "Chengdu", section = "JingJiang")
China Sichuan {'city': 'Chengdu', 'section': 'JingJiang'}>>>
3、匿名函数也是可以使用"关键字参数"进行参数传递:
>>> g= lambda x,y : x**2+y**2
>>> g(2,3)13
>>> g(y=3,x=2)13
lambda 匿名函数也可以设定默认值
>>> g= lambda x=0,y=0 : x**2+y**2
>>> g(2,3)13
>>> g(2)4
>>> g(y=3)9
4、对于变量作用域,变量的访问以 L(Local) –> E(Enclosing) –> G(Global) –>B(Built-in) 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
观察以下几个例子,均从内部函数输出变量 x:
1. 局部作用域
x = int(3.3)
x=0defouter():
x= 1
definner():
x= 2
print(x)
inner()
outer()
执行结果为 2,因为此时直接在函数 inner 内部找到了变量 x。
2.闭包函数外的函数中
x = int(3.3)
x=0defouter():
x= 1
definner():
i= 2
print(x)
inner()
outer()
执行结果为 1,因为在内部函数 inner 中找不到变量 x,继续去局部外的局部——函数 outer 中找,这时找到了,输出 1。
3.全局作用域
x = int(3.3)
x=0defouter():
o= 1
definner():
i= 2
print(x)
inner()
outer()
执行结果为 0,在局部(inner函数)、局部的局部(outer函数)都没找到变量 x,于是访问全局变量,此时找到了并输出。
4. 内建作用域
x = int(3.3)
g=0defouter():
o= 1
definner():
i= 2
print(x)
inner()
outer()
5、函数也可以以一个函数为其参数:
defhello () :print ("Hello, world!")defexecute(f):"执行一个没有参数的函数"f()
execute(hello)
输出:
Hello, world!
结束!