函数基础
定义:
1
2
3def name(param1, param2, ..., paramN):
statements
return/yield value # optional和其他需要编译的语言(比如C语言)不一样的是,def是可执行语句,这意味着函数直到被调用前,都是不存在的。当程序调用函数时,def语句才会创建一个新的函数对象,并赋予其名字。
- 调用函数时,必须保证这个函数此前已经定义过.
但如果在某函数内部调用其他函数,函数间哪个声明在前、哪个在后就无所谓,因为def是可执行语句,函数在调用之前都不存在,我们只需保证调用时,所需的函数都已经声明定义。
1
2
3
4
5
6
7
8
9
10def my_func(message):
my_sub_func(message) # 调用 my_sub_func() 在其声明之前不影响程序执行
def my_sub_func(message):
print('Got a message: {}'.format(message))
my_func('hello world')
# 输出
Got a message: hello world另外,Python函数的参数可以设定默认值, 如下。这样在调用函数func()时,如果参数param没有传入,则参数默认为0;而如果传入了参数param,其就会覆盖默认值。
1
2def func(param = 0):
...Python不用考虑输入的数据类型,而是将其交给具体的代码去判断执行,同样的一个函数(如一个相加函数),可以同时应用在整型、列表、字符串等等的操作中。编程语言中,我们把这种行为称为多态。这也是Python 和其他语言,比如Java、C等很大的一个不同点。
- 因此,在函数开头进行数据类型检查很重要
函数嵌套:
函数的嵌套能够保证内部函数的隐私。内部函数只能被外部函数所调用和访问,不会暴露在全局作用域,因此,如果你的函数内部有一些隐私数据(比如数据库的用户、密码等),不想暴露在外,那你就可以使用函数的的嵌套,将其封装在内部函数中,只通过外部函数来访问:
1
2
3
4
5
6def connect_DB():
def get_DB_configuration():
...
return host, username, password
conn = connector.connect(get_DB_configuration())
return conn合理的使用函数嵌套,能够提高程序的运行效率:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def factorial(input):
# validation check
if not isinstance(input, int):
raise Exception('input must be an integer.')
if input < 0:
raise Exception('input must be greater or equal to 0' )
...
def inner_factorial(input):
if input <= 1:
return 1
return input * inner_factorial(input-1)
return inner_factorial(input)
print(factorial(5))
函数变量作用域
- 如果变量是在函数内部定义的,就称为局部变量,只在函数内部有效。一旦函数执行完毕,局部变量就会被回收,无法访问.
- 想要在函数内部修改全局变量的值,需要在函数内部 用关键字 global 申明。
- 如果遇到函数内部局部变量和全局变是同名的情况,那么在函数内部,局部变量会覆盖全局变量
- 对于嵌套函数来说,内部函数可以访问外部函数定义的变量,但是无法修改,若要修改,必须加上nonlocal这个关键字
闭包 closure
闭包其实和刚刚讲的嵌套函数类似,不同的是,这里外部函数返回的是一个函数,而不是一个具体的值。返回的函数通常赋于一个变量,这个变量可以在后面被继续执行调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of # 返回值是 exponent_of 函数
square = nth_power(2) # 计算一个数的平方
cube = nth_power(3) # 计算一个数的立方
square
# 输出
<function __main__.nth_power.<locals>.exponent(base)>
cube
# 输出
<function __main__.nth_power.<locals>.exponent(base)>
print(square(2)) # 计算 2 的平方
print(cube(2)) # 计算 2 的立方
# 输出
4 # 2^2
8 # 2^3这里外部函数nth_power()返回值,是函数exponent_of(),而不是一个具体的数值。需要注意的是,在执行完square=nth_power(2)和cube=nth_power(3)后,外部函数nth power()的参数exponent,仍然会被内部函数exponent of()记住。这样,之后我们调用square(2)或者cube(2)时,程序就能顺利地输出结果,而不会报错说参数exponent没有定义了。
- 闭包常常和装饰器(decorator)一起使用。