数学上的函数通常形如y = f(x)
或者z = g(x, y)
这样的形式,在y = f(x)
中,f
是函数的名字,x
是函数的自变量,y
是函数的因变量;而在z = g(x, y)
中,g
是函数名,x
和y
是函数的自变量,z
是函数的因变量。Python中的函数跟这个结构是一致的,每个函数都有自己的名字、自变量和因变量。我们通常把Python中函数的自变量称为函数的参数,而因变量称为函数的返回值。
在Python中我们使用def
关键字来定义函数,关键字空格后面写函数名,函数名后的圆括号中写传递给函数的参数,也就是刚才说的自变量,圆括号外紧跟冒号。一个函数要执行的代码块(要做的事情)也是通过缩进的方式来表示的,跟之前分支和循环结构的代码块是一样的。而函数执行完成后我们会通过return
关键字来返回函数的执行结果,就是我们刚才说的函数的因变量。举例:
def add(a, b): c = a + b return c # 使用时,直接输入参数即可 print(add(5, 6)) # 11
**注意:**函数整体的的前后需要留白才是比较规范的做法。
如果函数中没有return
语句,那么函数默认返回代表空值的None
。另外,在定义函数时,函数也可以没有自变量,但是函数名后面的圆括号是必须有的。Python中还允许函数的参数拥有默认值,如果使用函数时没有传入新参数,则默认使用默认值举例:
# 定义摇色子的函数,n表示色子的个数,默认值为2 import random def roll_dice(n=2): """摇色子返回总的点数""" total = 0 for _ in range(n): # n = 2 total += random.randrange(1, 6) return total # 如果没有指定参数,那么n使用默认值2,表示摇两颗色子 print(roll_dice()) # 8
我们还可以实现一个对任意多个数求和的add
函数,因为Python语言中的函数可以通过星号表达式语法来支持可变参数。所谓可变参数指的是在调用函数时,可以向函数传入0个或任意多个参数。将来我们以团队协作的方式开发商业项目时,很有可能要设计函数给其他人使用,但有的时候我们并不知道函数的调用者会向该函数传入多少个参数,这个时候可变参数就可以派上用场。下面的代码演示了用可变参数实现对任意多个数求和的add
函数。
# 用星号表达式来表示args可以接收0个或任意多个参数 def add(*args): total = 0 # 可变参数可以放在for循环中取出每个参数的值 for val in args: total += val return total # 在调用add函数时可以传入0个或任意多个参数 print(add()) # 0 print(add(1)) # 1 print(add(1, 2)) # 3 print(add(1, 2, 3)) # 6 print(add(1, 3, 5, 7, 9)) # 25
全局变量(没有写在任何函数里面的变量)
局部变量(定义在函数内部的变量)
函数里面的局部变量和全局变量是两个不同的变量,相互没有关系各自不影响。
在Python程序中搜索一个变量是按照 LEGB 顺序进行搜索的:
Local
(局部作用域) —> Embeded
(嵌套作用域) —> Global
(全局作用域)
—> Built-in
(内置作用域)
如果在这四个里面都没找到就会报错:NameError: name … not defined
所以我们可以通过global
关键字声明使用全局变量或者定义一个局部变量将其放到全局作用域;nonlocal
关键字声明使用嵌套作用域的变量(不使用局部变量)。举例:
x = 100 def foo(): x = 200 print(x) # 输出局部变量x的值200 foo() print(x) # 输出全局变量x的值100
如果我不想在函数foo中定义局部变量x,想直接使用全局变量x,应该怎么做???
使用global
声明!
x = 100 def foo(): global x print(x) # 输出全局变量x的值100 foo() print(x) # 输出全局变量x的值100
如果我不想在函数bar中定义局部变量x,想直接使用嵌套作用域中的x,应该怎么做???
x = 100 def foo(): x = 200 x = x + 1 def bar(): nonlocal x x = 300 print(f'1.{x}') # 1.300 bar() print(f'2.{x}') #2.300 foo() print(x) # 100
如果同一个文件中有两个相同的函数,在我们调用时,会很容易出现问题。但是如果项目是团队协作多人开发的时候,团队中可能有多个程序员都定义了名为foo
的函数,这种情况下怎么解决命名冲突呢?
答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过import
关键字导入指定的模块再使用完全限定名的调用方式就可以区分到底要使用的是哪个模块中的foo
函数,代码如下所示。
module1.py
def foo(): print('hello, world!')
module2.py
def foo(): print('goodbye, world!')
test.py
import module1 import module2 # 用“模块名.函数名”的方式(完全限定名)调用函数, module1.foo() # hello, world! module2.foo() # goodbye, world!
在导入模块时,还可以使用as
关键字对模块进行别名,这样我们可以使用更为简短的完全限定名。
test.py
import module1 as m1 import module2 as m2 m1.foo() # hello, world! m2.foo() # goodbye, world!
上面的代码我们导入了定义函数的模块,我们也可以使用from...import...
语法从模块中直接导入需要使用的函数。这个方法同样可以使用as
关键词对模块进行别名。
test.py
from module1 import foo as f1 from module2 import foo as f2 f1() # hello, world! f2() # goodbye, world!
函数是功能相对独立且会重复使用的代码的封装。学会使用定义和使用函数,就能够写出更为优质的代码。当然,Python语言的标准库中已经为我们提供了大量的模块和常用的函数,用好这些模块和函数就能够用更少的代码做更多的事情。