函数基础
上来先看一个简单的例子吧
def sum_numbers(a,b):
return a+b
result = sum_numbers(3,5)
print(result)
# 输出
8
在调用函数时,必须在函数调用前声明函数,不然的话可能会报错。
result = sum_numbers(3,5)
def sum_numbers(a=0,b=0):
return a+b
print(result)
# 输出
NameError:name 'sum_numbers' is not defined
一般来说,我们会设置一个默认值,在不更改时使用默认值,大部分情况下,部分值一般不需要改动。
def sum_numbers(a=0,b=0):
return a+b
result = sum_numbers(3,5)
print(result)
# 输出
8
Python相对于其他语言的一个特点是,Python是动态类型语言,可以接受任何类型的数据(整型、浮点、字符串等),对于参数来说,这一点也适用,刚刚定义的sum_numbers函数我们也可以把列表作为参数来传递,表示将两个列表连接:
def sum_numbers(a,b):
return a+b
result = sum_numbers([1,3,5,7],[2,4,6,8])
print(result)
# 输出
[1, 3, 5, 7, 2, 4, 6, 8]
同样的,字符串也可以拼接
def sum_numbers(a,b):
return a+b
result = sum_numbers('welcome to ','https://reid.run')
print(result)
# 输出
welcome to https://reid.run
在Python中我们可以不用考虑输入数据的类型,我们将Python的这一特性称为多态,但是在实际使用中会带来许多问题,因此,必要是应该在开头加上数据的类型检查。
Python的另一大特性是,Python支持函数的嵌套,我们来看一个例子:
def f1():
print('hello')
def f2():
print('reid.run')
f2()
f1()
# 输出
hello
reid.run
函数的嵌套:
- 函数的嵌套能够保护函数内部的隐私,内部函数只能被外部函数访问,不会暴露在全局作用域,当通过pymysql访问数据库时,你肯定不希望(数据库用户和密码)暴露在外,那么就可以使用函数的嵌套,将其封装在内部函数中,只通过内部函数来访问。
- 合理的函数嵌套能够提高程序的运行效率。(例如:汉诺塔,递归计算一个数的阶乘)
函数变量的作用域
如果变量是在函数内部定义的,就称为局部变量,只在函数内部有效。当函数执行完毕,局部变量就会被收回,无法访问。
如果变量是定义在整个文件层次上的,那么这个变量就被称为全局变量。全局变量可以在函数内外访问,但是不能在函数内部改变全局变量的值。
MAX_NUMBER = 1
def change_number(value):
# 省略
MAX_NUMBER +=1
# 省略
change_number(2)
UnboundLocalError: local variable 'MAX_NUMBER' referenced before assignment
在Python中,Python解释权会默认在函数内部的变量为局部变量,但是又发现局部变量MAX_NUMBER没有声明,故无法调用,所以如果我们一定要在函数内部改变全局变量的值,就必须使用global声明:
MAX_NUMBER = 1
def change_number(value):
# 省略
global MAX_NUMBER
MAX_NUMBER += 1
# 省略
change_number(2)
这里的global关键字是用来声明,函数内部的MAX_NUMBER变量是之前定义的全局变量,它既不是新的全局变量,也不是函数内部的局部变量,这样,函数就能在函数内部修改全局变量的值。
当在函数内部和函数外部同时定义一个同名变量的情况下,Python解释器会优先读取内部变量的值:
MAX_NUMBER = 1 # 外部变量
def change_number():
MAX_NUMBER = 5 # 内部变量
return MAX_NUMBER
print(change_number())
# 输出
5
类似的,对于嵌套函数来说,内部函数可以访问外部函数定义的变量,但是无法修改,如果要修改则必须加上nonlocal关键字:
def outer():
x = 'local'
def inner():
nonlocal x # nonlocal关键词表示这里的x就是外部函数outer定义的变量x
x = 'nonlocal'
print('inner:',x)
inner()
print('outer:',x)
outer()
# 输出
inner: nonlocal
outer: nonlocal
# nonlocal关键词改变了外部变量 x 的值
如果不加上nonlocal关键字,而内部函数的变量和外部函数的变量同名,则内部函数变量会覆盖外部函数变量。
def outer():
x = 'local'
def inner():
x = 'nonlocal'
print('inner:',x)
inner()
print('outer:',x)
outer()
# 输出
inner: nonlocal
outer: local
# 没有nonlocal关键词,内部函数的变量覆盖了外部函数的变量
闭包
用一句话来说,闭包是由两个函数嵌套组成,外函数的返回值会内函数的引用,主要用于装饰器。
下面用伪代码来对闭包的格式描述:
def 外函数(参数):
def 内函数(参数):
print('内函数执行',参数)
return 内函数
内函数的引用 = 外函数('传入参数')
内层函数的引用()
下面来看一个简单的例子:
def func(a,b):
def line(x):
return a * x - b
return line
line = func(2,3)
result = line(4)
print(result)
# 输出
2 * 4 - 3 = 5
Q.E.D.