函数是带名字的代码块,用于完成特定的任务,当在程序中多次执行同一任务时,无需反复编写重复的代码块,只需调用执行该任务的函数即可。
函数的声明
在Python中使用 def 关键字来声明函数,每个函数都有一个的函数名,我们通过函数名调用函数。在函数名后面的圆括号中可以放置传递给函数的参数,当然函数也可以没有参数,没有参数的函数叫做无参函数。函数内容以 : 开始,并且函数体要缩进。在函数执行完成后可以通过 return 关键字来返回一个值给调用方,没有 return 语句相当于返回None。有关函数的说明写在声明函数的下方,称为文档字符串的注释,描述了函数的功能,用三引号括起,Python使用它们生成有关程序中函数的文档。下面的例子演示了如何声明一个无参函数并调用此函数。
def print_hello():
"""打印字符串“Hello”"""
print('Hello!')
print_hello()
输出结果为
Hello! |
下面的例子演示了如何声明一个含两个参数的函数并调用此函数。
def max(x, y):
"""返回两个数中较大的数"""
if x > y:
return x
else:
return y
print(max(3, 7))
最终程序运行的结果为
7 |
参数的传递
在Python中,对象可分为两类,一类是不可更改的对象,另一类则是可更改的对象。在传递参数过程中,如果传入的是不可更改的对象,则传递的只是值本身,调用函数后不会对原来的对象产生影响,例如:整数、字符串、元组等。但如果传入的是可更改的对象,则是对原来的对象进行操作,调用函数后,在此函数中对此对象进行的修改就是对原来的对象进行修改,例如列表、字典等。当然,不可更改的对象与可更改的对象这类说法不太严谨,在Python官方文档中也没有这种说法,这里只是为了区分出调用函数时更改的对象不同。下面的例子演示了传递不可更改对象的函数调用。
def not_change(x):
print('id(x) = ', id(x)) # 指向同一个对象
print('x = ', x) # x的值为传进来的参数值
x = 0 # 创建了新对象
print('x = ', x) # 新对象的值为0
print('id(x) = ', id(x))
if __name__ == '__main__':
y = 10
print('id(y) = ', id(y)) # 查看y指向的对象id
not_change(y) # 调用函数
print('y = ', y) # 调用后y的值并不会改变
print('id(y) = ', id(y)) # y还是指向调用函数前的对象
输出结果为
id(y) = 2719015594576 # 调用函数前y指向的对象id |
下面的例子演示了传递可更改对象的函数调用。
def change(list):
print('id(list) = ', id(list)) # 指向同一个对象
print('list = ', list) # list的值为传进来的参数值
list.append(100) # 直接在此对象上进行操作
print('list = ', list) # 操作后list的值更新了
print('id(list) = ', id(list)) # 对象还是传进来的那个对象
if __name__ == '__main__':
x = [10, 20, 30]
print('id(x) = ', id(x)) # 查看x指向的对象id
change(x) # 调用函数
print('x = ', x) # 调用函数后x指向的对象已经发生了改变
print('id(x) = ', id(x)) # 但对象id还是原来的那个对象
输出结果为
id(x) = 2074989554688 # 调用函数前x指向的对象id |
向函数传递实参
向函数传递实参的方式有位置实参、关键字实参、任意数量实参等方式。
位置实参
位置实参的传入必须与函数声明时参数的顺序一致。
def print_hello(name, age):
print(f'Hello! I am {name}, I am {age} years old.')
if __name__ == '__main__':
name = 'Mary'
age = 20
print_hello(name, age)
输出结果为
Hello! I am Mary, I am 20 years old. |
关键字实参
关键字实参方式可以在调用函数时使用关键字来确定传入的参数值,即在调用函数时参数的顺序可以不按声明时的顺序书写。
def print_hello(name, age):
print(f'Hello! I am {name}, I am {age} years old.')
if __name__ == '__main__':
a = 'Mary'
b = 20
print_hello(age=b, name=a)
输出结果为
Hello! I am Mary, I am 20 years old. |
默认参数
在声明函数时,可以在参数的后面添加参数的默认值,在调用函数而没有给定相应的参数时,会使用默认参数。注意:默认参数必须放在最后面。
def print_hello(name, age = 20):
print(f'Hello! I am {name}, I am {age} years old.')
if __name__ == '__main__':
name = 'Mary'
print_hello(name)
输出结果为
Hello! I am Mary, I am 20 years old. |
任意数量实参
有时候需要在函数中处理未知数量的参数,在声明函数时,可以使用 * 号标明传入一个元组形式的参数,调用函数时,会把收到的所有值都封装到这个元组中。
def print_numbers(*numbers):
print(numbers)
if __name__ == '__main__':
print_numbers(0, 1, 2, 3, 4, 5)
输出结果为
(0, 1, 2, 3, 4, 5) |
除此之外,还有带 ** 两个星号的写法,标明传入一个字典形式的参数。
def print_keys_value(**dict):
print(dict)
if __name__ == '__main__':
print_keys_value(name='Mary', age=20)
输出结果为
{'name': 'Mary', 'age': 20} |
函数的返回值
使用 return 语句可以指定该函数的返回值。对于没有return语句的函数定义,Python都会在末尾加上 return None ,使用不带值的return语句,也返回None。
def sum(*numbers):
total = 0
for x in numbers:
total += x
return total
if __name__ == '__main__':
print(sum(0, 1, 2, 3, 4, 5))
输出结果为
15 |
Lambda表达式
在Python中可以使用 Lambda 表达式创建匿名函数。Lambda 的主体是一个表达式,而不是一个代码块。Lambda 函数不能访问自己参数列表之外或全局命名空间里的参数。Lambda 表达式的格式为 lambda 参数列表:表达式 。
sum = lambda x, y: x + y
if __name__ == '__main__':
print(sum(4, 5))
输出结果为
9 |
调用模块中的函数
在工程项目中会经常遇到同名函数问题,即两个模块中都有一个函数名一样但功能不一样的函数,这时,如果要调用其中的一个函数,必须指定模块名。下面的例子演示了如何调用不同模块的同名函数。
# p1.py
def fuction():
print('p1 function')
# p2.py
def fuction():
print('p2 function')
# main.py
import p1
import p2
if __name__ == '__main__':
p1.fuction()
p2.fuction()
输出结果为
p1 function p2 function |
我们也可以在导入模块时给模块起别名,通过别名调用模块中的函数。
import math as m
if __name__ == '__main__':
print(m.fabs(-2))