注:python中无函数重载
格式:
def 函数名(参数列表): 函数体 #函数体需要有一个相对def语句的tab缩进
注:函数名亦可以作为实参传入函数
# 例:定义一个函数:生成10个[1,20)的随机数并打印
def fun():
for i in range(10):
ra = random.randint(1, 20)
print(ra)
fun()
# 例:定义一个函数:求两数和并返回
def addfun(a, b):
return a + b
print(addfun(1, 2))
# 求可迭代数据对象的最大值
def getmax(iterable):
maxi = iterable[0]
for i in iterable:
if i > maxi:
maxi = i
return maxi
print(getmax([2, 3, 1, 0]))
格式:
#形式1: def 函数名(*参数名):# 星号后的参数名一般用 args 函数体 #形式2: def 函数名(**参数名):# 星号后的参数名一般用 kwargs 函数体
可变参数必须位于参数列表末尾,且形式1和形式2最多出现一次,若两种形式同时出现,则*
必须位于**
之前
在底层进行实参与形参的匹配时,
*
的实参,则此容器变量会被整个看作原元组的一个元素*
进行拆包def fun(a, b, *c):
print(a, b, c)
fun(1,2)# 1 2 ()
fun(1, 2, 3)# 1 2 (3,)
fun(1,2,3,4)#1 2 (3, 4)
def fun(a, *c):
print(a, c)
tup = [3, 5]
fun(0,tup) # 0 ([3, 5],)
fun(0,*tup) ##0 (3, 5)
# 编写一个函数,实现求多个数据的和
def fun(*args):
sum_f = 0
if len(args) > 0:# 判断元组是否为空
for i in args:
if isinstance(i,int):#判断元素是否为整型变量
sum_f += i
print(sum_f)
fun(1, 2, 3)
key = value
的形式传参,**
表示拆包为key = value
的形式def fun(**info):
print(info)
fun()#打印 {}
fun(name='feng', age=19)#打印{'name': 'feng', 'age': 19}
dict_1 = {
'type': '001', 'weight': 65} #定义一个字典变量用于作为实参传递
fun(**dict_1)# 打印{'type': '001', 'weight': 65}
def fun(a, b, *c, **d):
print(a, b, c, d)
fun(1, 2) #打印 1 2 () {}
fun(1, 2, 3, 4)#打印 1 2 (3, 4) {}
fun(1, 2, x=5, y=6)#打印 1 2 () {'x': 5, 'y': 6}
fun(1, 2, 3, x=5, y=6) # 打印 1 2 (3,) {'x': 5, 'y': 6}
fun(1, 2, x=5, 3) # 出错
在参数列表中以key = value
的形式出现,
def 函数名(..., key = value, ...) 函数体
此参数在传参时可以省略,使用value值做为默认值
当参数列表中含有多个关键字参数时,参数的匹配会按参数列表中的顺序进行匹配
若想要给位于中后部的关键字参数传参,则需要以key = value
的格式完整的指明索要传参的参数和相应值.
def fun2(a, b=100,c = 200):
print(a + b + c)
fun2(10) #打印310
fun2(10,10) #打印220
fun2(10, c = 20) # 打印130
def fun(a, b=100, **c):
print(a, b, c)
fun(10) # 10 100 {}
fun(10,10,b=20) # 出错,在关键字参数与**的可变参数同时使用时,在为**参数赋值时的key值不可与其他参数名相同
使用关键字 return
def fun(a, b):
return a + b, a * b
x, y = fun(10, 20)
z = fun(10, 20)
print(x, y, z) # 30 200 (30, 200)
return
语句也可以返回内部函数,使得外部的变量可以接收函数的内部函数,从而通过此变量来调用函数的内部函数(闭包)def fun():
str = 'aaa'
def inner_fun(): #定义内部函数
print(str)
return inner_fun #在外部函数中将内部函数名作为返回值,注意不带括号
my_fun = fun() # 变量 my_fun 接收函数fun返回的内部函数
my_fun() # 通过变量名my_fun加上括号来实现调用内部函数的功能
声明在函数外面的变量称为全局变量,在代码块中定义的变量称为局部变量
若在函数中修改不可变的全局变量则会报错,而修改可变全局变量不会报错
str = 'aaa'#变量str为全局变量
def fun():
str += 'sss'#此处在函数中试图修改全局变量str,会报错
print(str)
解决:
使用关键字 global
在函数中,若想修改某不可变的全局变量的值,需要在函数内部的最前方添加带有global
关键字的变量声明
(global
声明要位于要修改全局不可变变量的函数内部,即若内部函数要修改其,则声明应置于内部函数中)
str = 'aaa'#变量str为全局变量
def fun():
global str #使用global关键字进行声明
str += 'sss'#此处对str的修改不会报错
print(str)
list_1 = [1, 2, 3, 4]#可变全局变量
def fun():
list_1.append(5)#在函数中不使用全局声明不会报错
print(list_1)
fun()
print(list_1)
在函数体中嵌套定义函数,
内部函数需要在函数内部调用才可以执行
带有内部函数的函数的底层处理步骤:
特点:
nonlocal
声明global
声明def fun():
lists = [9, 6, 5, 7, 3, 4]
print(lists)
def inner_fun():#内部函数
lists.sort()
print(lists)
inner_fun()#调用内部函数
fun()
def fun():
str = 'aaa'#str为不可变变量
def inner_fun():
str += 'bbb'#在内部函数中直接修改外部函数的不可变变量会报错
print(str)
inner_fun()
fun()#运行时会报错
def fun():
str = 'aaa'#str为不可变变量
def inner_fun():
str += 'bbb'#在内部函数中直接修改外部函数的不可变变量会报错
print(str)
inner_fun()
fun()#运行时会报错
def fun():
str = 'aaa'
def inner_fun():
nonlocal str #对要修改的外部函数变量进行nonlocal声明
str += 'bbb'
print(str)
inner_fun() #调用内部函数
fun()#此时可以正确运行
locals()
将局部符号表作为字典返回(将当前作用域中的变量及其值以字典的形式返回返回)def fun():
str = 'aaa'
print(locals()) #{'str': 'aaa'}
def inner_fun():
st = 'bbb'
inner_fun()
fun() # 打印结果{'str': 'aaa'}
由函数及其内部函数组成的一个整体
将内部函数名作为外部函数的返回值的形式成为闭包
可以使用一个变量接收此返回值,并通过变量名()
的方式实现在外部调用内部函数
def fun():
str = 'aaa'
def inner_fun(): #定义内部函数
print(str)
return inner_fun #在外部函数中将内部函数名作为返回值,注意不带括号
my_fun = fun() # 变量 my_fun 接收函数fun返回的内部函数
my_fun() # 通过变量名my_fun加上括号来实现调用内部函数的功能
保存参数状态
如下例,变量first_fun
接收了参数为1,2时的内部函数,变量second_fun
接收了参数为3,4时的内部函数,当调用first_fun
时,结果为当参数为1,2时的结果,即其保存了参数为1,2时的状态
def fun(a, b):
c = 10
def inner_fun():
print(a + b + c)
return inner_fun # 返回内部函数名
first_fun = fun(1, 2) # 将参数为1,2 时的内部函数赋值给变量
second_fun = fun(3, 4) # 将参数为3,4 时的内部函数赋值给变量
first_fun() # 打印 13
second_fun() # 打印 17
计数器
def fun():
con = [0]
def inner_fun():
con[0] += 1
print('当前是第{}此访问'.format(con[0]))
return inner_fun
counter = fun()
counter() # 当前是第1此访问
counter() # 当前是第2此访问
counter() # 当前是第3此访问
闭包同级访问
同级的内部函数可以互相调用
def fun():
a = 100
def inner_fun1():# 内部函数1
b = 90
s = a + b
print(s)
def inner_fun2():# 内部函数2
inner_fun1() # 调用内部函数1
print('内部函数2')
return 'aaaa'
return inner_fun2
f = fun()
s = f() # 打印 内部函数2
print(s)# 打印 aaaa
在不修改原函数的情况下扩充原函数的功能
def func():
print('函数func执行')
def test(f):#其参数为函数名
print('函数test执行')
print(f)
f()#执行参数函数
test(func)#调用函数test并将函数func的函数名作为参数传入
'''
打印结果:
函数test执行
函数func执行
'''
def my_decorate(func):#定义装饰器,其参数为函数名 a = 100 def wrapper():#装饰器的内部函数 func()#调用参数函数 print('1111') print('2222') return wrapper#返回内部函数 #使用装饰器,在要进行装饰的函数定义前添加注解 @装饰器名 @my_decorate #添加注解 def my_func():#定义被装饰函数my_func() print('0000') my_func() # 调用函数my_func() ''' 打印结果: 0000 1111 2222 '''
上述装饰器为自定义函数my_func()
增加了打印1111
和2222
的功能
def my_decorate(func):
a = 100
print('wrapper外层打印测试....')#添加输出语句
def wrapper():
func()
print('1111')
print('2222')
print('wrapper加载完成...')#在wrapper函数外添加输出语句
return wrapper
@my_decorate # 用装饰器修饰函数
def my_func():
print('0000')
# 此处并未调用被装饰的函数
'''
打印结果:
wrapper外层打印测试....
wrapper加载完成...
'''
装饰器的执行:
@装饰器名
处,底层自动进行以下处理
return
语句(装饰器使用了闭包的方式,因此其必定存在返回内部函数名的return
语句)若被装饰函数有参数,则装饰器的内部函数以及内部函数中进行调用参数函数的语句都应当带上参数,为了使装饰器可以适合多种参数列表的形式,可以采用两种可变参数作为装饰器内部函数的参数,并在其内部调用参数函数时将两个可变参数进行拆包传入.
import time
def my_decorate(func):
a = 10
def wrapper(*args, **kwargs):#装饰器内部函数带参数,为适合多种参数形式,因此采用可变参数
print('加载中,请稍后...')
time.sleep(2) # 等待2秒钟
print('加载完成')
func(*args,**kwargs)#调用参数函数时传入参数,此处应带上*及**进行拆包
return wrapper
@my_decorate
def f1(n):
print('--f1--', n)
f1(4)
@my_decorate
def f2(a, b):
print('--f2--', a, b)
f2(4, 5)
@my_decorate
def f3(lists):
for i in lists:
print(i)
names = ['lily', 'lucy', 'mike']
f3(names)
@my_decorate
def f4(a, age=12):
print('--f1--', a, age)
f4(18, age=10)
若装饰器要求带有参数,则此装饰器需要有三层
def outer(a): # 装饰器第一层,带有一个参数a,其负责接收装饰器的参数
def decorate(func): # 装饰器第二层,其负责接收被装饰函数
def wrapper(*args,**keargs): # 装饰器第三层.其负责接收被装饰函数的参数
func(*args,**keargs)
print('装饰'.format(a))
return wrapper # 返回第三层
return decorate # 返回第二层
@outer(10) # 添加装饰器并传入参数
def my_fun():
print('hahaha')
my_fun()
'''
打印结果:
hahaha
装饰10
'''
被装饰函数可以被多个装饰器同时装饰,但其装饰顺序采用就近原则,越靠近被装饰函数的就越先进行装饰
def decorate_1(func):#装饰器1
print('动作1---开始')
def wrapper():
func()
print('动作1--拿筷子')
print('act_1---结束')
return wrapper
def decorate_2(func):#装饰器2
print('动作2---开始')
def wrapper():
func()
print('动作2--拿馒头')
print('act_2---结束')
return wrapper
@decorate_1
@decorate_2
def eat():#被装饰函数,使用两个装饰器进行修饰
print('准备吃饭...')
eat()#调用被装饰函数
'''
动作2---开始
动作2---结束
动作1---开始
动作1---结束
准备吃饭...
act_2--拿馒头
act_1--拿筷子
'''
上例中装饰器距离被装饰函数最近,先由其进行装饰.
import time
islogin = False
def login(): # 登录模块
username = input('请输入用户名:\n')
pw = input('请输入密码:\n')
if username == 'admin' and '123456':
return True
else:
return False
# 定义一个装饰器,进行付款验证
def login_required(func):
def wrapper(*args, **kwargs):
# 验证用户是否已经登录
global islogin
if islogin:
func(*args, **kwargs)
else:
# 跳转到登陆模块
print('尚未登陆,请登录')
islogin = login()
print('result', islogin)
return wrapper
@login_required
def pay(money):
print('正在付款,付款金额为:{}'.format(money))
print('付款中')
time.sleep(2)
print('付款完成')
pay(100)
对于逻辑较少的函数(函数体只有一两行)可通过匿名函数的形式进行简化.
定义格式:
lambda 参数1,参数2...:运算 # 运算结果会自动return
匿名函数的调用:
使用一变量接收匿名函数,则此变量与匿名函数指向同一地址,可通过变量名()
的形式调用此匿名函数,匿名函数的运算结果会自动return
,因此也需要一变量接收匿名函数的返回值
如:
fun = lambda a, b: a + b # 定义匿名函数并用一变量接收此函数
sum=fun(1,2) # 调用匿名函数
匿名函数可以作为函数的参数
def fun(x, y, func): # 参数func为一函数参数
print(x, y)
print(func)
a = func(x, y)
print(a)
fun(1, 2, lambda a, b: a + b) # 将匿名函数作为参数传入
匿名函数与内置函数结合
如,内置函数max()
def max(*args, key=None): # known special case of max
"""
max(iterable, *[, default=obj, key=func]) -> value
max(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its biggest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the largest argument.
"""
pass
list2 = [{
'a': 10, 'b': 20}, {
'a': 13, 'b': 8}, {
'a': 2, 'b': 5} # 其为元素是字典的列表,
max_li = max(list2, key=lambda dic: dic['a'])#调用max()时指定器关键字参数key,使器在比较列表中的各个字典时按照字典中的'a'进行比较
print(max_li)
上例中列表的元素为字典类型,max()
函数无法直接比较字典的大小(字典无法使用>及<
进行比较),要想对其进行比较,需要使用max()
函数中的关键字参数,指定其为字典中的可比较类型,是的函数按照此类型对字典进行比较.
max()
函数的关键字参数key=func
,即其接收一个函数作为参数,默认值为None,在使用此参数时,可以使用匿名函数作为参数传入