function是一段有组织、可复用的代码,用来完成某个具体的任务。Functions为你的应用提供了更好的模块化,以及高度的代码复用。Python 和其他编程语言一样,都有内置函数(print、map等),随时可用。你也可以定义自己的函数,这类函数称为user-defined functions。函数可以简单到只向控制台打印一条消息,也可以相当复杂。
要执行函数内部的代码,需要调用这个函数,方法是在函数名后面加上括号 [()]。数据(也就是arguments)可以通过放在括号里传给函数。一个函数定义可以包含零个或多个parameters。形参定义了函数接受哪些实参。形参规定了要传入的实参是什么_类型_。实参则是调用函数时实际传入的_值_。根据传给形参的实参不同,函数可以完成不同的任务。
函数还可以使用return关键字返回值。函数返回的值称为 return value。返回值会交还给函数的调用者。
在 Python 中,函数使用 def 关键字创建。函数定义后面跟着函数名和括号 [()]。括号内指定形参,用逗号分隔。右括号之后,用冒号(:)把函数签名和函数体分开。
函数体是在调用函数时执行的一块代码。函数体需要缩进。缩进很重要,因为 Python 依靠它来判断这段代码在哪里结束。使用 return 关键字可以从函数返回值,返回值随后可供函数的调用者使用。
def function_name(parameter1, parameter2, ...):
# function body
return parameter1 + parameter2
我们也可以定义一个没有任何形参或返回值的函数。
def function_name():
# function body
pass
注意,函数确实需要一个函数体,即使函数体什么都不做,否则运行程序时会产生缩进错误:
>>> def my_bodyless_func():
...
File ~/temp.py:1
^
IndentationError: expected an indented block
要调用函数,使用函数名,后面加上括号 [()]。传给函数的实参放在括号内,用逗号分隔。
请看下面这个函数:
def greet():
print("Hello")
可以用下面的语法调用上面的函数:
>>> greet()
Hello
实参是调用函数时传给函数的值。它们可以是任何数据类型,包括其他函数或类。
我们来定义一个把两个数字相加的函数 add:
def add(first, second):
print(first + second)
形参 first 和 second 定义了 add 函数会接受哪些实参。(需要注意的是,parameter 和 argument 这两个词经常被混用,尽管这样并不准确。)调用函数时,实参会被传给函数。两个形参都需要传入实参,否则会引发 TypeError。
>>> add(2, 3)
5
# Function can be called multiple times, with different parameters
>>> add(4, 3)
7
>>> add(5, 6)
11
# Passing an incorrect number of parameters will raise a `TypeError`
>>> add(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'second'
>>> add(2, 3, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
返回值是交还给函数调用者的值。返回值可以是任何数据类型,包括其他函数或类。函数的调用者可以用它来做进一步的操作。如果函数没有显式定义返回值,Python 解释器会返回 None。
我们来定义一个函数 add:
def add(first, second):
return first + second
我们可以把返回值存进一个变量,然后打印出来:
>>> result = add(2, 3)
>>> print(result)
5
# Type of result is `int`
>>> type(result)
<class 'int'>
# We can also perform operations on the return value
>>> result * 2
10
# A function without an explicit return value will return `None`
>>> def log(message):
print(message)
# Hello is printed because of print(message), but return value is `None`
>>> return_value = log("Hello")
Hello
>>> return_value
None
使用 return 会立即退出函数,并把值返回给调用者。
>>> def show(first, second):
print(first)
return first
print(second)
# second never gets printed, because the function exits after the return statement
>>> show(1, 2)
1
复杂的程序可以拆分成更小的部分。不同的函数可以用来完成各自具体的任务。
假设一个程序需要完成以下任务:
我们可以把这个程序拆分成更小的部分。
def circle_area(radius):
return 3.14 * radius * radius
def rectangle_area(length, breadth):
return length * breadth
def triangle_area(base, height):
return 0.5 * base * height
现在,我们可以按自己想要的顺序调用这些函数。
>>> circle_area(2)
12.56
>>> triangle_area(2, 3)
3.0
>>> rectangle_area(2, 3)
6
>>> rectangle_area(1, 2) + circle_area(2) + triangle_area(1, 2)
15.56
如果一个变量(或名称)定义在函数内部,那么它只能在函数作用域(或局部命名空间)_内部_访问,即使函数作用域外存在同名变量也一样。
在函数之外、模块层级_定义的变量属于_全局命名空间。在函数之外、但在某个外层函数或类_内部_定义的变量属于_非局部命名空间_。
Python 在程序运行时使用 LEGB 规则(即局部、外层、全局、内置)来解析变量名:
如果该名称依然无法解析,Python 会引发 NameError exception。
# Global namespace.
general_favorite = "apples"
def alices_favorite():
# Local namespace.
favorite = "cherries"
# This works because Python will eventually find general_favorite in the global namespace.
# Python will find 'print' in the built-in namespace.
print(f'Alice has always liked {favorite}, but most people like {general_favorite}.')
def our_favorite_fruits():
# Enclosing or nonlocal namespace.
yours = "peaches"
def my_favorite():
# Local namespace.
mine = "pears"
# This works because Python will eventually find 'yours' in the enclosing/nonlocal namespace.
print(f'My favorite is {mine}, but you like {yours} instead.')
# This works because Python will eventually find 'general_favorite' in the global namespace.
print(f'Everyone seems to like {general_favorite}')
# This function is in the local namespace of the 'our_favorite_fruits' function.
my_favorite()
# This will raise NameError: name 'favorite' is not defined, because the variable favorite is local to alices_favorite.
print(favorite)
如果我们想让某个变量名在局部函数作用域_之外_也能访问(或者修改一个定义在函数作用域之外的变量),就需要使用 global 或 nonlocal 关键字。
使用 global 关键字会告诉 Python 从_全局命名空间_开始查找。此后对该变量的赋值会修改_全局_变量,而不会创建一个_局部_变量。用 global 声明变量时,这个变量会被_添加_到全局命名空间中。因此,应该谨慎使用 global,因为添加或修改全局变量可能会影响所有使用该变量值的其他代码。
nonlocal 关键字告诉 Python 在_非局部或外层命名空间_中查找/创建这个变量。当一个函数_嵌套_在另一个函数或类中,并且需要访问外层函数的变量和作用域时,就会用到它。
在 Python 中,函数可以赋值给变量,也可以作为实参传给其他函数。它们还可以用作返回值。函数可以放进序列(list、tuple等)中,也可以作为 dict 的值。凡是能用其他对象的地方,都能用函数。这是因为_函数是一等对象_。正因如此,它们带有一些特殊属性,甚至可以自行定义如何读取和设置自己的自定义属性。
# print is a function
# A function can be assigned to a variable.
>>> function_as_variable = print
>>> function_as_variable("Hello")
Hello
>>> type(fake_print)
<class 'builtin_function_or_method'>
# Functions can be passed as an argument to another function.
>>> def check_print(func):
func("Hello")
>>> check_print(print)
Hello
# Function can be used as an item in a sequence.
>>> my_list = [print, "Hello"]
>>> my_list[0]("Hello")
Hello
# Functions can be used as a value in a dictionary.
>>> my_dict = {"key": print}
>>> my_dict["key"]("Hello")
Hello
# Functions can be returned from a function.
>>> def return_func():
return print
>>> return_func()("Hello")
Hello
函数也可以嵌套在其他函数内部。
def outer():
num = 10
# This is a nested, or "inner" function.
def inner():
print(num)
# Outer function calling inner function
inner()
内部函数可以访问外层函数中定义的变量 num。
>>> outer()
10
Python 中的函数有一些特殊属性,其中包括:
__name__:函数名__doc__:函数的文档字符串__module__:定义该函数的模块__globals__:函数中的全局变量字典__code__:包含函数指令的代码对象>>> def add(first, second):
return first + second
# Function name
>>> print.__name__
'print'
>>> len.__name__
'len'
>>> add.__name__
'add'
# Function documentation
>>> abs.__doc__
'Return the absolute value of the argument.'
# Module
>>> len.__module__
'builtins'
>>> add.__module__
'__main__'
完整的函数属性列表可以在 Python 数据模型 中找到。