Python 测开28期 - aileen - 学习笔记 - Python基础知识-part2

Python编程语言学习笔记
四、函数
第五部分:函数
函数的定义,说明,传参,返回,及调用
def func_demo(name,age,nationnality=“中国”):
‘’’

:param name: 姓名
:param age: 年龄
:param nationnality: 国籍
:return: 姓名和年龄元祖
'''
if age > 18:
    print(f"姓名:{name} 已成年")
else:
    print(f"姓名:{name} 未成年")
print(f"国籍:{nationnality}")
#以元祖的形式返回参数
return name,age

str2=func_demo(“YangYang”,6)
print(str2)
#doc文档的引用1
#help(func_demo)
#doc文档的引用2
var = func_demo.doc
print(var)

第六部分:闭包函数
闭包定义:闭包是指在一个嵌套函数的内部访问外部函数定义的变量(或函数)的能力。换句话说,闭包是一个函数对象,它可以记住并访问它创建时的上下文环境中的变量。
#闭包函数及环境的定义,外包函数的修改
def out_func():
out_n = 100
def inner_func():
nonlocal out_n
out_n = 200
print(“inner:”,out_n)
print(“outer:”,out_n)
inner_func()
print(“outer:”,out_n)
return inner_func

func = out_func()
func()
输出:
image

第七部分:装饰器(闭包函数的应用)
装饰器是python提供的一种语法糖,装饰器使用@符号加上装饰器名称,用于修改其他函数的行为,并且在不修改原始函数的定义和调用的情况下添加额外的功能,本质上是一种闭包函数。装饰器的功能特点:

  • 不修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能
    由于装饰器的本质是一个闭包函数,所以在使用自定义装饰器之前,需要先定义一个用来作为装饰器的闭包,而闭包函数的外部函数名就作为装饰器名使用。
    #通用装饰器:以计算函数运行时间为例

import time
def func_time(func):
def inner_func(*args,**kwargs):
start_time = time.time()
result = func(*args,**kwargs)
end_time = time.time()
print(f"函数运行时间为:",{end_time - start_time})
return result
return inner_func

@func_time
def show():
sum = 0
for i in range(100001):
sum = sum + i
print(sum)

@func_time
def get_msg(msg):
return msg

@func_time
def display_msg(n,msg):
for i in range(n) :
print(msg)

#说明:装饰器在python解释器层面类似于: show = func_time(show)
show()
print(get_msg(“Horgwarts”))
display_msg(5,‘hello world’)

#带参数装饰器
#除了普通的装饰器使用方式之外,在使用装饰器时,还需要向装饰器传递一些参数,比如测试框架pytest在实现数据驱动时,可以将测试数据以装饰器参数形式传入,此时,前面定义的普通装饰器就不能满足要求。
#可以在通用装饰器外,再定义一层函数,用来接收装饰器的参数。
def decorator_args(vars,datas):
def decorator(func):
print(vars)
print(datas)
def inner_func(*args,**kwargs):
result = func(*args,**kwargs)
return result
return inner_func
return decorator

data = [(1,2,3),(4,5,6),(7,8,9)]

@decorator_args(‘a,b,c’,data)
def show(a,b,c):
print(a,b,c)

show(1,2,3)
运行结果:
image

#数据驱动例子理解
def decorator_args(vars,datas):
def decorator(func):
#将字符串分割备用
v_keys = vars.split(“,”)

    #定义保存[{},{},{}]的数据
    new_datas=[]
    #遍历数据,取出一组元素数据
    for item in datas:
        #定义一个新字典,用来保存变量名与传入数据组成的字典
        d_item = {}
        for k,v in zip(v_keys,item):
            d_item[k] = v
        #将组合好的字典追加到新数据中备用
        new_datas.append(d_item)


    def inner_func(*args,**kwargs):
        result = func(*args,**kwargs)
        return result

        #遍历新数据,取出元素字典
    for item in new_datas:  
        #将字典中的数据解包传给内涵数
        inner_func(**item)

    return inner_func


return decorator

data = [(1,2,3),(4,5,6),(7,8,9),(‘hello’,‘world’,‘Hogwarts’)]
@decorator_args(“a,b,c”,data)
def show(a,b,c):
print(a,b,c)

#作业:编写一个Python程序,实现一个计数器函数,该函数能够记录特定函数的调用次数。你需要使用闭包和装饰器来实现这个功能。

def func_counter(func):
times = 0
def inner_func(*args,**kwargs):
nonlocal times
result = func(*args,**kwargs)
times = times + 1
print(f"函数’{func.name}'被调用次数为",times)

    return result

return inner_func

@func_counter
def show(name):
print(‘hello’,name)

show(‘lily’)
show(‘Lucy’)
show(‘David’)
说明:关于闭包函数中外部函数变量的作用域进一步说明见链接:Python闭包及其作用域 - pluviophile - 博客园