第四篇 函数

函数可以实现代码的复用,对于多次调用的代码片段可以封装成函数以便于调用和后期维护。

1.定义函数与调用

1 def 函数名(参数):
2     函数体
3     return 返回值

注:

1.def是定义函数关键词,def和函数名之间需要有空格。

2.函数名为函数的名字,函数名可以为字符,数字和下划线,但是不能以数字开头。

3.参数为调用函数需要传入的参数。

4.返回值为调用函数后返回的值,不写return,默认返回None。

实例:

1 def sum(a,b):
2     return a+b
3 
4 sum=sum(12,13)
5 print(sum)
6 
7 ------输出结果------
8 25

注:调用函数直接使用函数名()即可,当然当函数需要参数时,需要在括号内传入指定的参数。

2.函数的返回值

函数的返回值就是调用函数后返回的值,如果函数中没有return关键字,则该函数默认返回None。

1)没有返回值

1 def sum(a,b):
2     s=a+b
3 
4 s=sum(12,13)
5 print(s)
6 
7 ------输出结果------
8 None

注:sum函数中没有return返回值,该函数默认返回了None,另外当return关键字后没有值,函数也是返回None,此用法常用来结束函数。

2)返回一个值

1 def sum(a,b):
2     s=a+b
3     return s
4 
5 s=sum(12,13)
6 print(s)
7 
8 -----输出结果-----
9 25

注:sum函数中返回了一个值s,然后把该值赋予s,并输出s的值。

3)返回多个值

1 def demoReturnMul():
2     return 1,"1,2",[1,2,3]
3 
4 print(demoReturnMul())
5 
6 -------输出结果------
7 (1, '1,2', [1, 2, 3])

注:可以看出,函数返回多个值,是以元组的形式返回的,实际上python把多个逗号分隔的值认为是元组。可以使用多个值进行接收,但是接收的变量的个数要与返回的值的个数相等。

3.函数的参数

1)形参和实参

形参是在定义函数时函数中的参数,实参是调用函数中传递给函数的参数。

2)多个参数

 函数可以定义多个参数,每个参数之间使用逗号分隔。

1 #a,b,c,d均为参数
2 def sum(a,b,c,d):
3     return a+b+c+d
4 
5 print(sum(1,2,3,4))
6 
7 -------输出结果------
8 10

3)位置参数

调用函数时根据定义函数时定义的参数来传递参数。

1 def hello_name(name,sex):
2     dicts={'1':'男士','2':'女士'}
3     print('hello %s %s,welcome you' %(name,dicts.get(sex)))
4 
5 hello_name("zhangsan",'1')
6 
7 --------输出结果-------
8 hello zhangsan 男士,welcome you

4)默认参数

定义函数时为函数提供默认参数,可以在调用函数时不传递该参数值,函数自动取该默认值,位置参数必须位于默认值参数前面。

1 def hello_name(name,sex='2'):
2     dicts={'1':'男士','2':'女士'}
3     print('hello %s %s,welcome you' %(name,dicts.get(sex)))
4 
5 hello_name("zhangsan")
6 
7 ------输出结果------
8 hello zhangsan 女士,welcome you

5)动态参数

函数参数前有一个*,则函数把参数值转换为一个元组,函数参数前有两个*,则函数把参数值转换为一个字典。

1 def print_name(*args):
2     print(args)
3 
4 print_name("zhangsan","lisi","wangwu","zhangliu")
5 
6 ------输出结果----
7 ('zhangsan', 'lisi', 'wangwu', 'zhangliu')
1 def print_name(**kwargs):
2     print(kwargs)
3 
4 print_name(name="zhangsan",age=18,sex='male')
5 
6 ---------输出结果-----
7 {'age': 18, 'sex': 'male', 'name': 'zhangsan'}

4.命名空间和作用域

1)命名空间

命名空间定义:变量名到对象的映射,各个命名空间是独立的关系,一个命名空间不能相同的变量名,不同的命名空间可以有相同的变量名。

命名空间分类:

1.全局命名空间:程序一运行就创建的命名空间。

2.局部命名空间:程序运行过程中创建的临时命名空间,如函数和类等。

3.内置命名空间:程序运行加载代码前创建的命名空间,用于存放python常用内置方法。

命名空间加载顺序:

内置命名空间(程序运行加载代码前)----全局命名空间(程序运行过程中,从上往下)----局部命名空间(程序运行中,从上往下)

命名空间取值顺序:

1.在局部调用:局部命名空间----全局命名空间----内置命名空间

1 i=1
2 def func():
3     i=2
4     print(i)
5 
6 func()
7 
8 -------输出结果------
9 2

2.在全局调用:全局命名空间----内置命名空间

1 print(len('hello'))  #没有自己定义len方法,调用的是系统内置的len方法
2 
3 -----输出结果------
4 5
1 def len(o):    #自己定义的len方法
2     return "调用的是非内置方法"
3 
4 print(len('hello'))  #由于调用顺序是全局命名空间,然后是内置命名空间,因此此处是调用自己定义的len方法
5 
6 ------输出结果-------
7 调用的是非内置方法

2.作用域

全局作用域:包括内置命名空间和全局命名空间,在整个文件中均可被调用,如果调用的位置在全局命名空间的前面,则调用的是内置命名空间的内容(如果有的话)。

1 print(len('hello'))  #因为自定义的方法在调用的方法后面,调用的是系统内置方法
2 
3 def len(o):
4     return "调用的是非内置方法"
5 
6 ------输出结果------
7 5

局部作用域:包括局部命名空间,只能在局部范围内有效。

global:用来声明一个全局变量,在局部作用域中想要对全局变量进行修改时可以使用此关键词进行声明。

1 i=1
2 def func():
3     i+=1
4     print(i)
5 
6 func()
7 
8 -----输出结果-----
9 UnboundLocalError: local variable 'i' referenced before assignment

上面报错了,因为i为全局变量,但是在func方法中对该变量进行修改,会认为是局部变量,但是i在局部中没有进行定义,因此会报错,可以在函数内把i声明为全局变量,这样就不会报错了。

 1 i=1
 2 def func():
 3     global i
 4     i+=1
 5     print(i)
 6 
 7 func()
 8 
 9 ------输出结果------
10 2

nonlocal:嵌套函数中内部函数修改外部变量的值。

 1 def outsideFunc():
 2     i=2
 3     def insideFunc():
 4         i+=2
 5         print(i)
 6     insideFunc()
 7 outsideFunc()
 8 
 9 ------输出结果------
10 UnboundLocalError: local variable 'i' referenced before assignment

可以看出在内部函数中想要对外部函数的变量进行修改,会报错,在内部函数中修改外部函数变量进行修改python会默认把变量进行隐藏,可以使用nonlocal关键词进行声明。

 1 def outsideFunc():
 2     i=2
 3     def insideFunc():
 4         nonlocal i
 5         i+=2
 6         print(i)
 7     insideFunc()
 8 outsideFunc()
 9 
10 -----输出结果-----
11 4

注:global和nonlocal的区别是global声明的变量为全局变量,而nonlocal声明的变量为外部函数的变量。

5.函数名的本质

函数名的本质实际上就是函数的内存地址。

1 def func():
2     pass
3 
4 print(func)
5 
6 -----输出结果----
7 <function func at 0x000002118E5C00D0>

1)函数名可以赋值给其他变量

1 def func():
2     print("函数调用了。。。")
3 
4 a=func
5 a()
6 
7 ------输出结果-----
8 函数调用了。。。

2)函数名可以当作容器类的元素

 1 def func1():
 2     print("func1函数调用了。。。")
 3 def func2():
 4     print("func2函数调用了。。。")
 5 def func3():
 6     print("func3函数调用了。。。")
 7 
 8 lists=[func1,func2,func3]
 9 
10 for i in lists:
11     i()
12 
13 -------输出结果-----
14 func1函数调用了。。。
15 func2函数调用了。。。
16 func3函数调用了。。。

3)函数名可以当作参数传递给其他函数

 1 def func1():
 2     print("func1调用了")
 3 
 4 def func2(func1):
 5     func1()
 6 
 7 func2(func1)
 8 
 9 ------输出结果-----
10 func1调用了

4)函数名可以当作返回值

 1 def func1():
 2     print("func1调用了")
 3 
 4 def func2(fun):
 5     return fun
 6 
 7 f=func2(func1)
 8 f()
 9 
10 ----输出结果-----
11 func1调用了

 6.闭包

闭包的定义:内部函数对外部函数非全局变量的引用,并且外部函数返回内部函数的引用(内存地址)。

实例:

 1 def outside():
 2     i=10
 3     def inside():
 4      
 5         print(i)
 6     return inside
 7 
 8 inside=outside()  #inside保存了内函数的内存地址
 9 inside()
10 
11 -----输出结果-----
12 12

使用__closure__判断函数是不是闭包函数:

 1 def outside():
 2     i=10
 3     def inside():
 4         print(i)
 5     print(inside.__closure__)
 6     return inside
 7 
 8 inside=outside()
 9 inside()
10 
11 -----输出结果----
12 (<cell at 0x000001F028D36D68: int object at 0x000000005B1E02F0>,)
13 10

猜你喜欢

转载自www.cnblogs.com/zhuzhaoli/p/10256460.html