基础

函数为实现了某一功能的代码片段,可以重复利用
函数可以返回调用结果(return or yield),也可以不返回

1
2
3
def name(param1, param2, ..., paramN):
statements
return/yield value # optional
  1. 编译型语言不同,def可执行语句,即函数直到被调用前,都是不存在
  2. 当调用函数时,def 语句才会创建一个新的函数对象,并赋予其名字

主程序调用函数时,必须保证这个函数已经定义过,否则会报错

1
2
3
4
5
my_func('hello world')  # NameError: name 'my_func' is not defined


def my_func(message):
print('Got a message: {}'.format(message))

函数内部调用其它函数,则没有定义顺序的限制
def可执行语句 - 函数在调用之前不存在,只需保证调用时,所需的函数都已经声明定义即可

1
2
3
4
5
6
7
8
9
def my_func(message):
my_sub_func(message) # Got a message: hello world


def my_sub_func(message):
print('Got a message: {}'.format(message))


my_func('hello world')

函数可以设定默认值

1
2
def func(param = 0):
...

Python 是 Dynamically Typed,可以接受任何数据类型,同样适用于函数参数
Python 不考虑输入的数据类型,而是将其交给具体的代码判断执行

该行为是多态,在必要时,需要加上类型检查

1
2
3
4
5
6
7
8
9
def my_sum(a, b):
return a + b


print(my_sum(1, 2)) # 3
print(my_sum([1, 2], [3, 4])) # [1, 2, 3, 4]
print(my_sum('Hello', 'World')) # HelloWorld

print(my_sum(1, 'Hello')) # TypeError: unsupported operand type(s) for +: 'int' and 'str'

Python 支持函数嵌套

1
2
3
4
5
6
7
8
9
10
11
def f1():
print('hello')

def f2(): # f2 is local to f1
print('world')

f2()


f1()
f2() # NameError: name 'f2' is not defined
  1. 函数嵌套可以保证内部函数的隐私
    • 内部函数只能被外部函数所调用和访问,不会暴露在全局作用域
  2. 合理地使用函数嵌套,可以提高程序的运行效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def factorial(input):
# validation check only once
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))

函数变量作用域

  1. 函数内部定义的变量,称为局部变量,只在函数内部有效
  2. 一旦函数执行完毕,那么局部变量就会被回收
  3. 全局变量则是定义在整个文件层次上,可以在文件内的任何地方被访问
1
2
3
4
5
6
7
8
9
MIN_VALUE = 1
MAX_VALUE = 10


def validation_check(value):
MIN_VALUE += 1 # UnboundLocalError: local variable 'MIN_VALUE' referenced before assignment


validation_check(5)

不能在函数内部随意改变全局变量的值 – 针对不可变对象,如 int 和 string

  1. Python 解析器会默认函数内部的变量局部变量
  2. 如果要在函数内部改变全局变量的值,必须加上 global 声明
    • 显式告知 Python 解释器,函数内部的变量就是之前定义的全局变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
MIN_VALUE = 1
MAX_VALUE = 10


def validation_check(value):
global MIN_VALUE
print(MIN_VALUE) # 1
MIN_VALUE += 1
print(MIN_VALUE) # 2


print(MIN_VALUE) # 1
validation_check(5)
print(MIN_VALUE) # 2

如果全局变量指向的对象是可变的,如 list 和 tuple,可以在函数内部修改

1
2
3
4
5
6
7
8
9
10
x = [1]


def func():
x.append(2)


print(x) # [1]
func()
print(x) # [1, 2]

如果函数内部局部变量和全局变量同名的情况下,在函数内部,局部变量会覆盖全局全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
MIN_VALUE = 1
MAX_VALUE = 10


def validation_check(value):
MIN_VALUE = 101 # This is a local variable, shadowing the global variable
print(MIN_VALUE) # 101
MIN_VALUE += 1
print(MIN_VALUE) # 102


print(MIN_VALUE) # 1
validation_check(5)
print(MIN_VALUE) # 1

对于嵌套函数来说,内部函数可以访问外部函数定义的变量,但无法修改,除非加上 nonlocal 关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
def outer():
x = "local"

def inner():
nonlocal x # nonlocal keyword is used to work with variables inside nested functions, where the variable should not belong to the inner function.
x = 'nonlocal'
print("inner:", x) # inner: nonlocal

inner()
print("outer:", x) # outer: nonlocal


outer()

如果没有 nonlocal 关键字,并且内部函数的变量与外部函数的变量同名,则会覆盖

1
2
3
4
5
6
7
8
9
10
11
12
def outer():
x = "local"

def inner():
x = 'nonlocal' # x is a local variable of inner function, shadowing the outer x
print("inner:", x) # inner: nonlocal

inner()
print("outer:", x) # outer: local


outer()

闭包

Closure - 常与 Decorator 一起使用

  1. 嵌套函数类似,但外部函数返回的是一个函数,而不是一个具体的值
  2. 返回的函数,可以被赋予一个变量,便于后续的执行调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def nth_power(exponent):
def exponent_of(base):
return base ** exponent

return exponent_of # return the function itself


square = nth_power(2)
cube = nth_power(3)

print(type(square)) # <class 'function'>
print(type(cube)) # <class 'function'>

print(square(2)) # 4
print(cube(3)) # 27