函数就是一段封装好的,可以重复使用的代码,它使得我们的程序更加模块化,避免大量重复的代码。
1.函数声明
'''
def 函数名(参数列表):
'''
# 函数文档
params:
return:
'''
# 实现特定功能的多行代码
[return [返回值]] #可选
#各部分参数定义:
函数名:一个符合 Python 语法的标识符,最好见名知意,多个单词可以使用_表示,比如cal_sum
形参列表:设置该函数可以接收多少个参数,多个参数之间用逗号( , )分隔。
[return [返回值] ]:整体作为函数的可选参参数,用于设置该函数的返回值。
python的函数体是通过冒号+缩进声明的
'''
2.函数调用
函数的声明并没有执行函数中的代码块,想要执行函数体,需要进行函数调用,一个函数可以调用多次。
函数调用语法:
# 函数名() # 不考虑参数和返回值的调用
def foo():
print("foo函数")
foo()
3.函数参数
3.1形参和实参
在函数的定义阶段 括号内写的变量名,叫做该函数的形式参数,简称形参。在函数的调用阶段,括号内实际传入的值,叫做实际参数,简称实参。
形参就相当于变量名,而实参就相当于变量的值,函数调用传参的过程 就是给形参变量名赋值的过程。
函数参数只有在函数调用阶段有效,函数运行结束,参数作为垃圾释放。
3.2位置参数
位置参数,有时也称必备参数,指的是必须按照正确的顺序将实际参数传到函数中,换句话说,调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致。
3.3默认参数
Python 允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。
def print_stu_info(name,age,gender="male"):
print("学员姓名:",name)
print("学员年龄:",age)
print("学员性别:",gender)
print_stu_info("张三",23)
当定义一个有默认值参数的函数时,有默认值的参数必须位于所有没默认值参数的后面,否则报错!
3.4关键字参数
关键字参数可以避免牢记参数位置的麻烦,令函数的调用和参数传递更加灵活方便。关键字参数是指使用形式参数的名字来确定输入的参数值。通过此方式指定函数实参时,不再需要与形参的位置完全一致,只要将参数名写正确即可。
def print_stu_info(name,age,height,weight,job):
print("学员姓名:",name)
print("学员年龄:",age)
print("学员身高:",height)
print("学员体重:",weight)
print("学员工作:",job)
print_stu_info("张三",23,"180cm","80kg","销售")
print_stu_info(name="张三",height="180cm",weight="90kg",job="销售",age=23)
print_stu_info("张三",height="180cm",weight="90kg",job="销售",age=23)
使用位置参数和关键字参数混合传参的方式。但需要注意,混合传参时关键字参数必须位于所有的位置参数之后。
3.5不定长参数
在函数定义中使用*args
和**kwargs
传递可变长参数。*args
用作传递非命名键值可变长参数列表(位置参数);**kwargs
用作传递键值可变长参数列表。*args
的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。**kwargs
的参数会以字典的形式导入。
# *args
def add(*args):
print(args)
print(type(args))
ret = 0
for i in args:
ret += i
print(ret)
add(12,23,45)
# **kwargs
def print_stu_info(**kwargs,):
print(kwargs)
print_stu_info(name="张三",height=190)
# *args + **kwargs
def print_stu_info(name, age=18, *args, **kwargs):
print(name, age)
print(args)
print(kwargs)
print_stu_info("yuan", 20, "China", "Beijing", height="188cm", weight="60kg")
注意点:
1、参数arg
、*args
、**kwargs
三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)
这个顺序,否则程序会报错。
2、不定长参数的长度可以为零。
3、args
和 kwargs
其实只是编程人员约定的变量名字,args
是 arguments 的缩写,表示位置参数;kwargs
是 keyword arguments 的缩写,表示关键字参数。
4.函数返回值
4.1基本使用
def add(x,y):
return x+y # return是函数的终止语句
ret = add(2,3)
print(ret)
4.2默认返回值
在 Python 中,有一个特殊的常量 None(N 必须大写)。和 False 不同,它不表示 0,也不表示空字符串,而表示没有值,也就是空值。None 是 NoneType
数据类型的唯一值(其他编程语言可能称这个值为 null、nil 或 undefined),也就是说,我们不能再创建其它 NoneType
类型的变量,但是可以将 None 赋值给任何变量。
Python一个函数中如果没有return语句或者return后没有具体值,都默认返回None,比如print()函数就没有返回。
4.3返回多个值
return也可以返回多个值,python其实会将多个值放在一个元组中元组返回。
def login(user,pwd):
flag = False
if user == 'yuan' and pwd == 123:
flag = True
return flag,user
# ret = login("yuan",123)
flag,user = login("yuan",123)
if flag:
print("{}登陆成功!".format(user))
else:
print("用户名或者密码错误!")
5.函数嵌套
def foo():
def bar():
print("bar功能")
print("foo功能")
foo()
6.作用域
所谓作用域(Scope),就是变量的有效范围,就是变量可以在哪个范围以内使用。有些变量可以在整段代码的任意位置使用,有些变量只能在函数内部使用。
LEGB含义解释
字母 | 英语 | 释义 | 简称 | 作用空间 |
---|---|---|---|---|
L | Local(function) | 当前函数内的作用域 | 局部作用域 | 局部 |
E | Enclosing Functions Locals | 外部嵌套函数的作用域 | 嵌套作用域 | 局部 |
G | Global(module) | 函数外部所在的命名空间 | 全局作用域 | 全局 |
B | Built In(python) | Python内置模块的命名空间 | 内建作用域 | 内置 |
# 案例1
def foo():
x = 10
foo()
print(x)
# 案例2
x = 100
def foo():
x = 10
foo()
print(x)
# 案例3
x = 100
def foo():
x = 10
print(x)
foo()
print(x)
# 案例4
x = 100
def foo():
print(x)
foo()
# 案例5
x = 100
def foo():
x = 12
def bar():
x = 1
print(x)
bar()
foo()
7.匿名函数
lambda 表达式,又称匿名函数,常用来表示内部仅包含 1 行表达式的函数。如果一个函数的函数体仅有 1 行表达式,则该函数就可以用 lambda 表达式来代替。
#格式如下
# name = lambda [list] : 表达式
其中,定义 lambda 表达式,必须使用 lambda 关键字;[list] 作为可选参数,等同于定义函数是指定的参数列表;value 为该表达式的名称。
def add(x, y):
return x+ y
print(add(2,3))
(lambda x,y:x+y)
(2,3)
可以这样理解 lambda 表达式,其就是简单函数(函数体仅是单行的表达式)的简写版本。相比函数,lambda
表达式具有以下 2 个优势:
- 对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁;
- 对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。
8.高阶函数
8.1高阶函数定义
一个高阶函数应该具备下面至少一个特点:
- 将一个或者多个函数作为形参
- 返回一个函数作为其结果
# 一切皆数据,函数亦是变量
def foo():
print("foo")
foo = 10
foo()
#如上代码将报错
#高阶函数 之 将函数作为形参的应用案例;计算某函数的运行时长
import time
#计算函数的运行时长
def timer(func):
s1 = time.time()
time.sleep(3)
func()
s2 = time.time()
print(s2 - s1)
def foo():
print('foo功能...')
def bar():
print('bar功能...')
timer(foo)
timer(bar)
#高阶函数 之 返回一个函数
def foo():
print('foo...')
def bar():
print('bar...')
return bar
# foo() #此时执行foo()不会执行bar函数中的代码块,仅会声明bar函数
ret = foo()
print('分割线.....')
ret()
8.2常见函数
#常见内置函数
bool
bin
oct
hex
sum
max
min
abs
pow
divmod
round
chr
ord
list
dict
set
len
any
all
zip
sorted
# ----------------------------------------------- sorted函数 -----------------------------------------------
stu_dict = {1001: {"name": "yuan", "score": {"chinese": 100, "math": 90, "english": 80, "average": 90}},
1002: {"name": "alvin", "score": {"chinese": 100, "math": 100, "english": 100, "average": 100}},
1003: {"name": "rain", "score": {"chinese": 80, "math": 70, "english": 60, "average": 60}}
}
# 按着平均成绩排序
stu_list = [v for k,v in stu_dict.items()]
ret = sorted(stu_list,key=lambda stu:stu["score"]["average"],reverse=True)
print(ret)
# ----------------------------------------------- zip函数 -----------------------------------------------
# 可以将多个序列(列表、元组、字典、集合、字符串以及 range() 区间构成的列表)“压缩”成一个 zip 对象。
# 所谓“压缩”,其实就是将这些序列中对应位置的元素重新组合,生成一个个新的元组。
my_list = [1, 2, 3]
my_tuple = [4, 5, 6]
print(list(zip(my_list, my_tuple)))
#常见高阶函数
# ----------------------------------------------- (1)filter函数 -----------------------------------------------
# 对sequence中的item依次执行function(item),将执行结果为True的item组成一个List/String/Tuple(取决于sequence的类型)。
def foo(x):
if x % 2 == 0:
return True
l = [1, 2, 3, 4]
print(list(filter(foo, l)))
print(list(filter(lambda x: x % 2 == 0, l)))
# ----------------------------------------------- (2)map函数 -----------------------------------------------
# 对sequence中的item依次执行function(item),将function(item)执行结果(返回值)组成一个List返回
def bar(x):
return x * x
l = [1, 2, 3, 4]
print(list(map(bar, l)))
print(list(map(lambda x: x * x, l)))
# -----------------------------------------------(3)reduce函数 -----------------------------------------------
# 函数将一个数据集合(列表,元组等)中的所有数据进行下列操作:
# 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,
# 得到的结果再与第三个数据用 function 函数运算,最后得到一个结果,逐步迭代。
from functools import reduce
def bar(x, y):
return x * y
l = [1, 2, 3, 4]
print(reduce(bar, l))
print(reduce(lambda x, y: x * y, l))
9.闭包
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。
简单来说就是一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。这样的一个函数我们称之为闭包。
闭包需要满足以下三个条件:
1、必须是一个嵌套函数
2、必须返回嵌套函数
3、嵌套函数必须引用外部非全局的局部自由变量
def foo():
x = 10
def inner(): #此时inner函数为一个闭包函数
print(x)
print("bar功能!")
return inner
func = foo()
func()
def foo(x):
def inner():
print(x)
print("bar功能!")
return inner
func = foo(12)
func()
价值:能够动态灵活的创建以及传递函数,体现出函数式编程的特点。所以在一些场合,我们就多了一种编码方式的选择,适当的使用闭包可以使得我们的代码简洁高效。
10.装饰器
import time
def foo():
print("foo功能")
time.sleep(2)
def bar():
print("bar功能")
time.sleep(3)
def timer(target_func):
def wrapper():
start = time.time()
target_func()
end = time.time()
print("时耗", end - start)
return wrapper
foo = timer(foo)
foo()
bar = timer(bar)
bar()
11.迭代器
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
11.1可迭代对象和迭代器
在具体讲迭代器之前,先了解一个概念:可迭代对象(Iterable
)。之前在数据类型中介绍的容器对象(列表,元组,字典,集合等)都是可迭代对象;从语法形式上讲,能调用__iter__
方法的数据对象就是可迭代对象:
12.生成器