所谓函数,就是把具有独立功能的代码块组织为一个小模块,在需要的时候调用。函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的重用。函数的使用包含两个步骤:
- 定义函数 —— 封装独立的功能
- 调用函数 —— 享受封装的成果
1. 函数定义
def func(*args):
"""文档字符串"""
pass
-
python使用def关键字定义函数
-
参数列表:形参,可有可无(冒号不可省略)
- 形参:函数定义时的参数
- 实参:函数调用时传入的参数
-
文档字符串解释函数功能,使用func_name.__doc__获取文档字符串
-
函数体定义函数具体功能:
- 返回值使用return关键字
- 函数执行到return语句时,函数执行完毕,并将结果返回。若无return语句,函数执行完毕,默认返回None
- 函数返回多个值时,默认以元组形式返回
- pass语句:占位,保证函数正常运行
-
参数类型检查:isinstance(obj, (class_or_tuple)) 对传入的参数类型进行判断,避免出现参数类型错误
2. 变量
-
python变量分为局部变量(内部变量)和全局变量(外部变量)
- 全局变量:所有作用域均可访问的变量
- 局部变量:函数或类内部创建的变量,只能由声明它的函数或类访问
- 全局变量和局部变量重名时,全局变量被屏蔽
-
python中def、class、lambda关键字可改变变量作用域,其为封闭作用域
-
if/elif/else、while/for、try/except/finally等不改变变量作用域
-
变量引用时,按照以下顺序查找:局部变量、包含该函数的外部非全局变量、全局变量、内置名称表
-
global语句:在函数或类内部修改全局变量需使用global关键字,实际判断是否要用global关键字在于看是否要修改该变量的指向。若修改指向(修改不可变类型)使用global,未修改(可变类型:如列表对象内部的值)则可是不使用。
-
nonlocal语句:将后面变量关联到最近的封闭作用域里面的同名变量(不包括全局变量),一般用于闭包里面修改外部函数的变量。
3. 函数调用
使用函数名加()进行函数调用:func_name()
if __name == "__main__":
func_name()
- 被引入时,__name__为文件名
- 自己执行,__name__为__main__(可打印__name__查看名字)
- 函数名可以赋值给一个变量,也可使用变量名()进行调用。
def func(*args):
"""文档字符串"""
print("函数使用演示。")
if __name__ == "__main__":
print(func.__doc__)
func()
new_func = func
new_func()
# 执行结果
文档字符串
函数使用演示。
函数使用演示。
4. 函数参数
4.1 位置参数
函数调用时需要按照函数定义时的形参顺序传入对应实参,且参数个数要相同。位置参数基于顺序的关联方式传入。
# 位置参数
def func(name, language):
"""打印喜欢的语言"""
print("my name is %s.I like %s." % (name, language))
func("fengdi", "python")
4.2 关键字参数
- 关键字实参是函数调用时根据形参传入对应的键值对形式,故无需考虑传入的顺序
- 若同时有位置参数和关键字参数,位置参数应位于关键字参数之前
# 关键字参数(命名参数)
def func(name, age, language):
"""打印喜欢的语言"""
print("my name is %s.I am %d years old. I like %s." % (name, age, language))
func("fengdi", language="python", age=19)
- 第一个参数以位置参数形式传入自动赋值给形参name,后两个参数以关键字参数形式传入,无需考虑传入的顺序。
4.3 默认参数值
- 可在定义函数时,为函数形参提供默认值
- 调用函数时,若对具有默认值的参数传入值,则使用,否则使用默认值
# 默认参数值
def func(name, language="java"):
"""打印喜欢的语言"""
print("my name is %s.I like %s." % (name, language))
func("fengdi", "python")
func("fengdi")
# 执行结果如下:
my name is fengdi.I like python.
my name is fengdi.I like java.
- 默认值不能为可变数据类型 ,下次执行时会积累上次执行后的值
def func(name, languages=["python", "java"]):
"""打印喜欢的语言"""
languages.append("c#")
print("my name is %s." % name)
for language in languages:
print("language: %s" % language)
func("fengdi")
func("fengdi")
# 执行结果
my name is fengdi.
language: python
language: java
language: c#
my name is fengdi.
language: python
language: java
language: c#
language: c#
4.4 收集参数(不定长参数)
- *args:将传入的多余的位置参数组成一个名为args的元组,在函数内部进行使用
# *args
def func(name, *args):
print("my name is %s" % name)
print(type(args), args)
for language in args:
print("- %s" % language)
func("fengdi", "python", "java")
# 执行结果:
my name is fengdi.
<class 'tuple'> ('python', 'java')
- python
- java
- **kwargs:将传入的多余的关键字参数组成一个名为kwargs的字典,在函数内部使用
# **kwargs
def func(language, **kwargs):
print("I like %s" % language)
print(type(kwargs), kwargs)
for name, language in kwargs.items():
print("%s's favorite language is %s." % (name, language))
func("python", fengdi="java", yuxi="c#", jack="php")
# 执行结果
I like python.
<class 'dict'> {'fengdi': 'java', 'yuxi': 'c#', 'jack': 'php'}
fengdi's favorite language is java.
yuxi's favorite language is c#.
jack's favorite language is php.
- 当多个参数位于元组或字典中时,可使用*或**分拆参数列表(参数解包)
# 参数解包
def func(a, b, c):
print("a+b+c:%s" % str(a+b+c))
num = (3, 4, 5)
func(*num)
def func(name, language):
print("my name is %s.I like %s." % (name, language))
info = {"name":"fengdi", "language":"python"}
func(**info)
执行结果
a+b+c:12
my name is fengdi.I like python.
5. 递归函数
- 一个函数内部调用自己的行为称为函数递归
- 函数内部可以调用其他函数(函数嵌套),当然在函数内部也可以调用自己
代码特点
- 函数内部的代码是相同的,只是针对参数不同,处理的结果不同
- 当参数满足一个条件 时,函数不再执行。这个非常重要,称为递归的出口,否则会出现死循环。
# 求阶乘
def factorial(num):
if num == 1:
return 1
else:
return num * factorial(num - 1)
result = factorial(5)
print(result)
6. 匿名函数
- python提供lambda关键字来创建匿名函数,即没有名字的函数,适用于创建临时性的、小巧的函数,不用考虑函数名冲突
- 形式:lambda 参数:表达式(只有一个)
- 冒号后面为函数返回值,此处不使用return关键字
# 匿名函数
func = lambda x : x ** 2
result = func(5)
print(result)