【函数】
1.什么是函数:
函数是可以重复执行的语句块,可以重复使用
2.作用:
1.用于封装语句块,提供代码的重用性
2.定义用户级别的函数
3.内建函数:
len() min () max() sum() print()
4.函数的(定义)创建:
语句:
def 函数名(形参列表):
语句块
def 语法说明:
1.函数名就是语句块的名称
2.函数的命名规则和变量名相同(函数名必须为标识符)
3.函数名是一个变量
4.函数有自己的名字和空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,
通常让函数处理外部给的数据需要用参数传递给函数使用
5.函数不需要参数,参数列表可以为空
6.语句部分不能为空,如果为空需要填充pass语句
5.函数的调用:
函数名(实际调用传递参数列表)
注:实际调用传递参数以后称为实参
说明:
函数调用是一个表达式
如果没有return语句,此函数执行完毕后返回None对象
如果函数需要返回其它的对象需要用到return语句
6.return语句:
语法:
return [表达式]
[]可省略
作用:
用于函数中,【结束当前函数的执行,返回到调用函数的地方】,同时返回一个对象的引用关系
说明:
1.return语句后跟的表达式可以省略,省略后相当于return None
2.如果函数没有return语句,则函数执行完后最后一条语句后返回None(相当于在最后加了一条return None语句)
3.函数调用一定会返回一个对象的引用
示例:
def myfun(a,b):
s = a + b
print('和是:',s)
v = myfun(3,5)
print('v = ',v)
----------------
和是: 8
v = None
----------------
def myfun(a,b):
s = a + b
print('和是:',s)
return 10000
v = myfun(3,5)
print('v = ',v)
----------------
和是: 8
v = 10000
----------------
7.函数的参数传递:
0.传递方式:(两种四类)
位置传递
序列传参
关键字传参
字典关键字传参
1.位置传参:
1.实际参数(实参)的对应关系与形式参数(形参)的对应关系是按位置来依次对应的
2.说明:
实际参数和形式参数通过位置进行传递的匹配
实参个数必须和形参个数相同
3.形式参数:
创建函数和定义函数过程中小括号里面的参数def add(name) name就是形参
4.实际参数:
函数在被调用过程中传递进来的参数 def add('小甲鱼') ‘小甲鱼’就是实参
2.序列传参:
序列传参是指在函数调用过程中,用*号将序列拆解后按位置传参的方式进行参数传递
序列的元素个数必须和参数个数相同
注意:序列传参要加'*'号
序列的位置信息对应的参数位置
示例:
def myfun(a,b,c):
print('a绑定的是:',a)
print('b绑定的是:',b)
print('c绑定的是:',c)
s = [1,2,3]
myfun(*s)
3.关键字传参:
是指传参的时候,按着形参的名称给形参赋值
实参和形参按名称进行匹配
说明:
实参可以不按位置给定
4.字典关键字传参:
通过字典进行匹配,字典的值传递给键对应的形式参数
是指实参为字典,将字典用** 拆解后进行关键字传参
说明:
字典的键名和形参名必须一致
字典的键名必须为字符串
字典的键名要在形参中存在
示例:
def myfun(a,b,c):
print('a绑定的是:',a)
print('b绑定的是:',b)
print('c绑定的是:',c)
d = {'a':11,'b':22,'c':33}
myfun(**d)
9.函数的形参(如何接受实参):
函数的缺省参数:
语法:
def 函数名(形参名1 = 默认实参1,形参名2 = 默认实参2....):
说明:
缺省参数必须从右至左依次存在,如果一个参数有缺省参数,则右侧的所有参数都必须有缺省参数
缺省参数可以有0个、1个或多个,甚至全部都可以有缺省参数
缺省参数的绑定对象是存在于函数内部的,同函数的生命周期一致
示例:
def info(name,age=15,address='未填写'):
print(name,age,address)
info('小张',15) # '小李' 15 '未填写'
info('小李')
10.函数的形参定义方式:
位置形参
星号元组形参
命名关键字形参
双星号字典形参
1.位置形参:
语法:
def 函数名(形参名1,形参名2,.....):
语句块
2.星号元组形参:
语法:
def 函数名(*元组形参名):
语句块
作用:
收集多余的位置形参
说明:
元组形参名通常用args
示例:
def func(*args):
print('整个参数是:',len(args))
print('args = ',args)
func(1,2,3,4)
func('hello','world',1,2,3)
------------------------------------
整个参数是: 4
args = (1, 2, 3, 4)
整个参数是: 5
args = ('hello', 'world', 1, 2, 3)
-------------------------------------
3.命名关键字形参:
语法:
def 函数名(*,命名关键字形参):
语句
(注意:单独一个*号表示语法标识,它没有收集参数的功能,仅代表*后面的是要用关键字形参表示)
或
def 函数名(*args,命名关键字形参):
语句
作用:
所有的命名关键字形参都强制调用者采用关键字传参或者字典关键字传参方式传递
即所有的参数都必须用关键字传参或字典关键字传参
示例:
def myfun(a,b,*args,c,d):
print('a=',a)
print('b=',b)
print('*args=',args)
print('c=',c)
print('d=',d)
myfun(3,4,5,6,7,8,c= 100,d=200)
输出:
a= 3
b= 4
*args= (5, 6, 7, 8)
c= 100
d= 200
---------------------------------------
4.双星号字典形参:
语法:
def 函数名(**字典形参名):
语句块
作用:
收集多余的关键字传参
说明:
字典形参名字通常叫做**kwargs
示例:
def func(**kwargs):
print(len(kwargs))
print(kwargs)
func(name = 'tarena',age = 15)
输出:
2
{'age': 15, 'name': 'tarena'}
--------------------------------------
11.函数的参数说明:
缺省参数,位置形参,星号元组形参,命名关键字形参,双星号字典形参可以混合使用
函数参数从左至右的顺序为:
位置形参
星号元组形参
命名关键字形参
双星号字典形参
示例:
>>> def fn(a,b,*args,c,**kwargs):
print(args)
print(kwargs)
>>> fn(1,2,3,4,c = 5,d = 6,e = 7)
(3, 4)
{'d': 6, 'e': 7}
>>> fn(*'hello',d = 6,**{'c':5,'e':7})
('l', 'l', 'o')
{'d': 6, 'e': 7}
------------------------------------------
12.函数的不定长参数:
def fn(*args,**kwargs):
psss
可以接受任意的位置传参和关键字传参
>>> def fn(*args,**kwargs):
print(args)
print(kwargs)
>>> fn(1,2,3,4,5)
(1, 2, 3, 4, 5)
{}
>>> fn(1,2,3,4,5,e = 7)
(1, 2, 3, 4, 5)
{'e': 7}
13.全局变量和局部变量:
1.局部变量:
定义在函数内部的变量成为局部变量(函数的形参也是局部变量)
局部变量只能在函数内部使用
局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁
2.全局变量:
定义在函数外部,模块内部的变量成为全局变量
全局变量,所有的函数都可以直接访问(但函数内部不能将其直接赋值)
3.说明:
1.在函数内首次对变量赋值是创建局部变量,再次为变量赋值是修改局部变量的绑定关系
2.在函数内部的赋值语句不会对全局变量造成影响
3.局部变量只能在其被声明的函数内部访问,而全局变量可以在整个模块范围内访问
4.globals和locals函数:
globals() 返回当前全局作用域内变量的字典
locals() 返回当前局部作用域内变量的字典
示例:
a = 1
b = 2
c = 3
def fn(c,d):
e = 300
print('locals()返回:',locals())
print('----------------------')
print('globals()返回',globals())
for k,v in globals().items():
print(k,'--->',v)
fn(100,200)
--------------------------------------
locals()返回: {'d': 200, 'e': 300, 'c': 100}
globals()返回的比较大,连文件名都出来了,这里不做打印,自己可以调试下
------------------------------------------------------------------
14.函数变量:
1.函数名是变量名,它在创建函数时绑定一个函数
示例:
>>> def fn():
print('f1被调用')
>>> fn()
f1被调用
>>> fx = fn
>>> fx() # 等同于fn()
f1被调用
>>> del fn # 删掉fn对fx没有影响
>>> fx()
f1被调用
--------------------------------------------
2.一个函数可以作为另一个函数的传递
示例:
def f1():
print('hello')
def f2():
print('world')
def fx(fn):
print(fn)
fn()
fx(f1)
fx(f2)
------------------------------------------
<function f1 at 0x7fa82b484f28>
hello
<function f2 at 0x7fa829cfdc80>
world
------------------------------------------
3.函数可以返回另一个函数(即另一个函数可以返回一个函数)
示例:
def get_fx():
s = input('请输入您要做的操作:')
if s == '求最大':
return max
elif s == '求最小':
return min
elif s == '求和':
return sum
l = [2,4,6,8,10]
print(l)
f1 = get_fx()
print(f1(l))
# print(get_fx(l)) 注意,直接这样是错的,括号里面是没有参数的,要绑定一个对象才可以
--------------------------------------------
[2, 4, 6, 8, 10]
请输入您要做的操作:求和
30
--------------------------------------------
15.函数嵌套(内嵌函数):
函数嵌套定义是指一个函数里用def语句来创建其他的函数
允许函数内部创建另一个函数
示例:
>>> def fun1():
print('fun1()正在被调用')
def fun2():
print('fun2()正在被调用')
fun2()
>>> fun1()
fun1()正在被调用
fun2()正在被调用
---------------------------------------------------
def fn_outer():
print('fn_outer被调用')
def fn_inter():
print('fn_inter被调用')
fn_inter()
return fn_inter
fn_outer()
print('---------------')
fx = fn_outer()
print('---------------')
fx()
---------------------------------------------------------
fn_outer被调用
fn_inter被调用
--------------------------
fn_outer被调用
fn_inter被调用
---------------
fn_inter被调用
-----------------------------------------------------------
16.python作用域:
作用域也叫名字空间,是访问变量时,查找变量名的范围空间
python的四个作用域(LEGB):
局部作用域(Local function L)
外部嵌套函数作用域(Encllosing Function Locals E)
函数定义所在模块(文件)的作用域(Global(Mudule G))
python内置模块(内建函数)的作用域(Builtin(python) B)
变量名的查找规则:
L ---> E ----> G ----> B
在默认的情况下,对变量名赋值会创建或改变本作用域内的变量
17.global语句和nonlocal语句:
global语句
作用:
1.告诉解释器,global语句生明的一个或多个变量,这些变量的作用域为模块级的作用域,也称作全局变量
2.全局声明(global)将赋值变量映身到模块文件内部的作用域
3.(global关键字可在局部变量中修改全局变量的值)
示例:
>>> count = 5
>>> def myfun():
global count
count = 10
print(count)
>>> myfun()
10
>>> count
10
---------------------------
说明:
1.全局变量如果要在函数内部被赋值,则必须经过全局声明(否则会认为是局部变量)
2.全局变量在函数内部不经过声明就可以直接访问
3.不能先声明局部变量,再用global声明为全局变量,此做法不符合规则
4.global变量列表里的变量不能出现在此作用域内的形参列表里
示例:
(第4点,这样必然出错)
v = 100
def f2(v):
global v # 此处必然出错
v = 300
f2(200)
print(v)
---------------------------------------
nonlocal语句:
作用:
在内部函数里可以修改外部函数里的局部变量的值(只对上一层进行操作)
告诉解释器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量名1,变量名2.....
说明:
1.nonlocal语句只能在被嵌套函数内部进行使用
2.访问nonlocal变量将对外部嵌套函数的作用域的变量进行操作
3.当有两层或两层以上的函数嵌套时,访问nonlocal变量只对最近一层的变量进行操作
4.nonlocal语句的变量列表里的变量名,不能出现在此函数的参数列表中(不能跟形参名一样)
示例:
>>> def funX():
x = 5
def funY():
nonlocal x
x *= x
return x
return funY
>>> funX()()
25
------------------------------------------
18.lambda表达式(匿名函数):
作用:
创建一个匿名函数对象
同def类似,但不提供函数名
如果对他进行使用,只需要进行简单的赋值操作即可
省下定义函数的过程,不需要考虑命名的问题,简化代码的可读性
语法:
lambda [参数1,参数2,...] : 表达式
冒号(:)左边放原函数的参数,可以有多个,用逗号(,)隔开,冒号右边是返回值
[] 里的内容可以省略
语法说明:
1.lambda只是一个表达式,它用来创建一个函数对象
2.当lambda表达式调用时,先执行冒号后的表达式,并返回表达式的结果的引用
3.lambda表达式创建的函数只能包含一条‘表达式’
4.lambda比函数简单,且可以随时创建和销毁,有利于减少程序的耦合度
示例:
>>> lambda x:2 * x + 1
<function <lambda> at 0x02DD8390>
>>> g = lambda x:2 * x + 1
>>> g(5)
11
-----------------------------------
19.eval()和exec()函数:
eval()函数:
格式:
eval(source,global=None,locals=None)
作用:
把一个字符串当成一个表达式来执行,返回表达式执行后的结果
示例:
x = 100
y = 200
a = eval('x' + 'y')
print(a)
>>> eval('1+2+3')
6
----------------------------------------------------
exec()函数:
格式:
exec(source,globals=None,locals=None)
作用:
把一个字符串当成程序来执行
示例:
>>>x = 100
>>>y = 200
>>> s = 'z = x + y;print(z);del z;print("删除成功")'
>>> s
'z = x + y;print(z);del z;print("删除成功")'
>>> exec(s)
300
删除成功
eval和exec的两个参数globals和locals:
此两个参数是用来设置'表达式'或'程序'运行的全局变量和局部变量
示例:
>>> x = 100
>>> y = 200
>>> s = 'print(x,y,x+y)'
>>> exec(s)
100 200 300
>>> exec(s,{'x':10,'y':20})
10 20 30
>>> exec(s,{'x':10},{'y':2})
10 2 12
>>> exec(s,{'x':10},{'x':1,'y':2})
1 2 3
---------------------------------------------------------
20.函数式编程:
函数式编程是指用一系列函数来解决问题
函数是一等公民:
函数本身可以赋值给变量,赋值后变量绑定函数
允许将函数本身作为实参传入另一个函数
允许函数返回一个函数
21.函数的可重入性:
可重入性是指一个函数传的参数一定,则结果必须一定
要求:
def定义的函数不要访问除局部变量以外的变量
示例:
# 以下是不可重入的函数,受外界影响大(y)
y = 200
def myadd(x):
return x + y
print(myadd(10))
y = 300
print(myadd(10))
# 以下是可重入的函数
def myadd(x,y):
return x + y
print(myadd(10,20))
-----------------------------------------
22.高阶函数(High Order Function):
1.满足下列一个条件的函数即为高阶函数:
1.函数接受一个或多个函数作为参数传入
2.函数返回一个函数
2.python中内键的的高阶函数:
map , filter, sorted
3.【map函数:】
1.map(func,*iterables) 用函数和对可迭代对象中的每一个元素作为参数计算出【新的可迭代对象,】
当最短的一个可迭代对象不在提供数据时,此可迭代对象生成结束。
2.即将序列的每一个元素作为函数的参数进行运算加工,直到可迭代对象每个元素都加工完毕,返回所有加工后的元素构成的新序列
3.在编程领域里,map一般作“映射”来解释。两个参数,一个函数和一个可迭代序列。
示例:
>>> list(map(lambda x:x * 2,range(10)))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
----------------------------------------------
>>> for x in map(pow,range(1,10),range(4,0,-1)):
print(x)
1
8
9
4
# 1**4,2**3,3**2,4**1
------------------------------------------------
4.【filter函数】
格式:
filter(func,itrable)
作用:
筛选可迭代对象中的数据,返回一个可迭代对象,对于所有的元素进行求值,返回False则丢弃,True则保留
示例:
>>> def odd(x):
return x % 2
>>> temp = filter(odd,range(10))
>>> list(temp)
[1, 3, 5, 7, 9]
(如果是偶数,求余之后为0,0是False值,而filter是把True值筛选出来)
-----------------------------------------------------------------------
# 把100以内所有的素数打印出来
def prime(x):
for i in range(2,x):
if x <=1:
return False
if x % i == 0:
return False
return True
m = filter(prime,range(2,100))
print(m)
print([y for y in m])
----------------------------------------------------------------------
5.【sorted函数】
作用:
将原可迭代对象的数据进行排序,生成排序后的列表
返回一个新的列表,原列表不变
格式:
sorted(iterable,key=None,reverse=False)
说明:
iterable是一个可迭代对象
key函数是用来提供一个参考值,这个值将作为排序的依据
reverse 标识用来设置是否降序排序
示例:
(key函数的用法)
>>> l = [5,-2,-4,0,3,1]
>>> l
[5, -2, -4, 0, 3, 1]
>>> l2 = sorted(l,key=abs)
>>> l2
[0, 1, -2, 3, -4, 5]
-----------------------------------------------------------
naems = ['Tom','Jerry','Spiker','Tyke']
l = sorted(naems,key = len)
print(l)
# 根据姓名的长度进行排序
['Tom', 'Tyke', 'Jerry', 'Spiker']
-----------------------------------------------------------
naems = ['Tom','Jerry','Spike','Tyke']
def aaa(i):
return i[::-1]
aaa(naems)
l = sorted(naems,key = aaa)
print(l)
# 根据姓名的反向进行排序
['Spike', 'Tyke', 'Tom', 'Jerry']
-----------------------------------------------------------
23.递归函数(recursion):
函数直接或间接的调用自身的行为
说明:
1.递归一定要控制递归的层数,当符合某一条件时要终止递归
2.几乎所有的递归都能用while循环来代替
优缺点:
优点:
递归可以把问题简单化,让思路更清晰,代码更简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
递归函数的实现方法:
先假设函数已经实现
示例:
def fx(n):
print('递归进入第',n,'层')
if n == 3:
return
fx(n + 1)
print('递归退出第',n,'层')
fx(1)
print('程序结束')
递归进入第 1 层
递归进入第 2 层
递归进入第 3 层
递归退出第 2 层
递归退出第 1 层
程序结束
----------------------------------------------------------
24.闭包closure
将内嵌函数的语句和这些语句的执行环境打包在一起时,得到的对象成为闭包
从表现形式上定义为:
如果在一个内部函数里,对在外部作用域(但不在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)
闭包必须满足三个条件:
1.必须有一个内嵌函数
2.内嵌函数必须引用外部函数的变量
3.外部函数返回值必须是内嵌函数
示例:
def make_power(y):
def fx(x):
return x ** y
return fx
pow2 = make_power(2)
print('3的平方是:',pow2(3))
3的平方是: 9
# 内部函数fx()就是一个闭包
# 在内部函数(引用了y)对外部作用域(不在全局作用域)的变量y进行引用
-------------------------------------------------------------------
# 用参数返回相应的数学函数的示例
# 二元一次方程y = a*x**2 + b*x + c
def make_function(a,b,c):
def fx(x):
return a*x**2 + b*x + c
return fx
fx1 = make_function(4,5,6)
# 创建一个y = 4x^2 + 5x + 6
print(fx1(2))
# 当x=2时
------------------------------------------------------------------
屏蔽情况:
>>> def funX():
x = 5
def funY():
x *= x
return x
return funY
>>> funX()()
UnboundLocalError: local variable 'x' referenced before assignment
python认为在内部函数的x是局部变量的时候,外部函数的x就被屏蔽起来了,所以执行x*x=x的时候
在右边根本找不到局部变量x的值,因此报错。
解决方法:
用nonlocal关键字,希望在内部函数里可以修改外部函数里的局部变量的值
----------------------------------------------------------------------------
25.装饰器decorators(专业提高篇):
函数装饰器是指装饰的是一个函数,传入的是一个函数,返回的也是一个函数的函数
函数装饰器的语法:
def 装饰器函数名(参数):
语句块
return 函数对象
被装饰函数的语法:
@装饰器函数名
def 函数名(形参列表):
语句块
示例:
# 定义装饰器函数解决问题
def mydeco(fn):
def fx():
print('++++++++++++')
fn()
print('------------')
return fx
# 定义函数的地方
@mydeco
def myfunc():
print('myfunc被调用')
# myfunc = mydeco(myfunc)
myfunc()
myfunc()
myfunc()
(!!!注意:@mydeco其实等价于myfunc = mydeco(myfunc))
----------------
++++++++++++
myfunc被调用
------------
++++++++++++
myfunc被调用
------------
++++++++++++
myfunc被调用
------------
--------------------------------------------------
带有参数的装饰器及应用案例:
# 第一步、添加一个余额变动短消息提醒功能
def messend_send(fn):
def fx(name,x):
print('发送消息',name,'来银行办理业务...')
fn(name,x)
print('发送消息',name,'办了',x,'元的业务....')
return fx
# 第二步,加一个权限验证功能的装饰器
def priviliged_checd(fn):
def fx(name,x):
print('正在检查权限...')
if True:
fn(name,x)
return fx
@priviliged_checd
# 银行业务:存钱(savemoney)、取钱(withdraw)
@messend_send
def savemoney(name,x):
print(name,'存钱',x,'元')
@messend_send
def withdraw(name,x):
print(name,'取钱',x,'元')
savemoney('小李',200)
savemoney('小赵',500)
withdraw('小王',300)
--------------------------------------------------
正在检查权限...
发送消息 小李 来银行办理业务...
小李 存钱 200 元
发送消息 小李 办了 200 元的业务....
正在检查权限...
发送消息 小赵 来银行办理业务...
小赵 存钱 500 元
发送消息 小赵 办了 500 元的业务....
发送消息 小王 来银行办理业务...
小王 取钱 300 元
发送消息 小王 办了 300 元的业务....
-----------------------------------------------------
25.函数的文档字符串:
函数内部,第一个没有赋值给任何变量的字符串为文档字符串
作用:
函数的文档字符串的作用是描述该函数的功能,当然,这是给别人看的
适当的文档说明非常重要,大型的程序都是团队完成的,大家的代码要相互衔接,就要阅读别提供的文档
功能:
它的功能跟注释是一样的。但文档字符串可以通过特殊属性__doc__获取
它是不会被打印出来的,但会作为函数的一部分存储起来
语法:
def 函数名(形参列表):
'''函数的文档字符串'''
函数语句块
函数的__doc__属性:
__doc__属性用于绑定该函数的文档字符串
另外:想用一个函数却不确定其用法的时候,会通过help()函数来查看函数的文档。
示例:
>>> def exchangeRate(dollar):
'''美元->人民币
汇率暂定为6.5
'''
return dollar * 6.5
>>> exchangeRate(10)
65.0
>>> exchangeRate.__doc__
'美元->人民币\n\t汇率暂定为6.5\n\t'
>>> help(exchangeRate)
Help on function exchangeRate in module __main__:
exchangeRate(dollar)
美元->人民币
汇率暂定为6.5
---------------------------------------------------------------
函数的__name__属性:
__name__属性用于绑定函数名的字符串
示例:
>>> f = lambda x:x+1
>>> f.__name__
'<lambda>'
-------------------------------------------------------------
26.函数定义语句(def语句的语法):
[@装饰器名1]
[@装饰器名2]
...
def 函数名([位置形参],[*[元组形参名]],[命名关键字形参],[**字典形参]):
"""文档字符串”“”
语句块
注:[]里的内容看代表可省略
27.函数的可变类型对象特殊情况:
默认参数(缺省参数)绑定在函数对象内部,且随函数的生命一直存在。
变得不可重入了。
示例:
l = [1,2,3]
def f(n,lst=[]):
lst.append(n)
print(lst)
f(4,l)
f(5,l)
f(100)
f(200)
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[100]
[100, 200]
-----------------------------------------------
解决办法:
l = [1,2,3]
def f(n,lst=None):
if lst is None:
lst = []
lst.append(n)
print(lst)
f(4,l)
f(5,l)
f(100)
f(200)
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[100]
[200]
-----------------------------------------------