python 生成器 迭代器 装饰器

本文详细介绍了Python中的生成器、迭代器和装饰器。生成器节省内存,适用于处理大数据;迭代器用于访问集合元素,可使用isinstance判断和next()方法;作用域和闭包涉及到变量范围和使用寿命;装饰器是闭包的应用,用于增强函数功能,如日志记录、时间统计等,可通过@语法糖方便使用。文中给出了多个装饰器的实例,包括带参数的装饰器和嵌套装饰器,展示了如何实现登录验证和函数运行日志记录等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生成器

生成器与列表推导式十分类似,将定义的括号由[]改为(),特点是调用一次,运算一次,占用的内存少,可以在for中使用,在处理大数据的时候,可以使用生成器,使用next()方法来生成下一个值,当生成器中的值都完成后,再次调用生成器会出现StopIteration的错误
在这里插入图片描述
还可以使用生成器来生成斐波那契数列,使用循环来抛出结果

def fib(times):
	n = 0
	a, b = 0, 1
	while n<times:
		yield b
		a, b = b, a+b
		n += 1

for item in fib(6):
	print(item)

在这里插入图片描述
使用next来抛出结果,超出范围的仍然会报错

# -*- enoding: utf-8 -*- 

def fib(times):
	n = 0
	a, b = 0, 1
	while n<times:
		yield b
		a, b = b, a+b
		n += 1

f = fib(6)
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))

在这里插入图片描述

迭代器

迭代器,用来访问集合元素的一种方式,只前进不后退,可以使用isinstance来判断一个对象是否可以迭代,使用之前需要先导入判断迭代的工具,然后再进行判断,生成器都可以迭代,迭代器也可以使用next()方法来调用,可迭代的对象要转换成迭代器的话需要使用iter()函数在这里插入图片描述
在这里插入图片描述

作用域和闭包

作用域:这个概念在其他语言中变现为命名空间,可以防止命名冲突,一个变量的作用域为,本地变量(局部变量),闭包,全局变量,内建模块
闭包:就是在一个函数内再定义一个函数,内部的函数可以直接使用外部函数的变量,函数的参数为局部变量,闭包的使用可以延长局部变量的使用寿命

装饰器

装饰器:有了以上的两个概念,就可以介绍装饰器,其实装饰器就是一个闭包,把一个函数当做参数传入另一个函数中,增强函数的功能但是不改变原来的函数,相当于一个语法糖,小技巧的东西。装饰器的作用可以由用户来定制,比如引入日志,做程序运行时间统计,执行函数前进行预处理,执行函数后清理,权限校验,缓存。这些操作会将被装饰的函数替换成新的函数,加载模块的时候立即执行。在使用装饰器的时候只需要在原函数的上方加上@装饰器名 就可以使用了。这就是动态语言的优点,为对象动态的添加属性和方法。
装饰器就是将函数作为参数传入,示例

def day2(function):
	print("hello,world")
	return function


#在被装饰的函数上方加上装饰标识
@day2
def day1():
	print("I am a function, named %s"%day1.__name__)
	

def main():
	day1()
	
	
if __name__=="__main__":
	main()

在这里插入图片描述
可以看出在装饰器中的语句也被执行了
做一个装饰器嵌套来观察装饰器代码的运行顺序

#定义装饰器,将传入的函数返回,装饰器必须放在被装饰函数的前面
def decorate_albert(function):
	print("start run",decorate_albert.__name__)
	#函数嵌套
	def wapper():
		print("开始运行",wapper.__name__)
		print("my name is ",wapper.__name__)
		print("结束运行函数")
	return wapper

def decorate_albert2(function):
	print("start run",decorate_albert2.__name__)
	return function

#定义一个函数
#如果是嵌套两层的装饰器,
@decorate_albert
@decorate_albert2
def albert():
	print("my name is %s"%albert.__name__)


def main():
	albert()
	
	
if __name__=="__main__":
	main()

在这里插入图片描述
可以看出首先执行的是在下方的装饰器,然后向外层冒泡,直到最外一层的装饰器,最后执行被装饰的函数。还可以给装饰器传参数,示例:

#给装饰器函数传参
def deco_func(func):
	print("I am a function named %s"%deco_func.__name__)
	def wapper(*args,**kw):
		print("start to run",wapper.__name__)
		print(args,kw)
		func(*args,**kw)
		print("function end",wapper.__name__)
	return wapper


#定义一个函数用来被装饰
@deco_func
def print_name(name,age):
	print("I am a function named %s"%print_name.__name__)
	print(f"your name is {name},your age is {age}")
	
	
def main():
	print_name("albert",23)
	
	
if __name__=="__main__":
	main()

在这里插入图片描述
但是在加入装饰器的时候原来函数的名字和参数也会被改变,为了消除这种负面影响,可以通过偏函数wraps来消除,在使用之前需要先从工具中引入

from functools import wraps
#给装饰器传递参数名字,在装饰器定义一个新的函数,然后将参数传入
def deco_para(name):
	def deco_func(func):
		print("I am a function named %s"%deco_func.__name__)
		#解决函数地址改变的方法,加一个偏函数,记住原来函数的名字
		@wraps(func)
		def wapper(*args,**kw):
			print("start to run",wapper.__name__)
			print(args,kw)
			func(*args,**kw)
			print("function end",wapper.__name__)
			print("I am a decorate named %s"%name)
		return wapper
	return deco_func


#定义一个函数用来被装饰
@deco_para("Decorate_name")
def print_name(name,age):
	print("I am a function named %s"%print_name.__name__)
	print(f"your name is {name},your age is {age}")
	
	
def main():
	print_name("albert",23)
	
	
if __name__=="__main__":
	main()

在这里插入图片描述
可以看出函数名字还是原来的print_name,然后将这个函数形式改写为类形式,更易读易扩展。

from functools import wraps


class Decorate():
	
	
	#初始化装饰器类,并命名
	def __init__(self,name):
		self.name=name
		
	
	#定义装饰器类的功能,并且传入参数
	def __call__(self,func):
		@wraps(func)
		def wappers(*args,**kw):
			print("I am a function named",wappers.__name__)
			print(*args,**kw)
			func(*args,**kw)
			print("end function",wappers.__name__)
			print("I am a decorate named %s"%self.name)
		return wappers
		
		
#实例化装饰器类,创建一个对象
@Decorate("de_albert")
def print_name(name,age):
	print("I am a function named %s"%print_name.__name__)
	print(f"my name is {name},my age is {age}")
	
	
def main():
	print_name("albert",23)
	
	
if __name__=="__main__":
	main()

在这里插入图片描述
执行结果与上面的函数一致。接下来利用以上的知识就可以做一些需求了,比如说实现一个记录函数运行的日志,再加上一个登陆的验证

#定义一个装饰器功能,实现记录函数运行日志,登录验证
from functools import wraps


class Decorate(object):


	def __init__(self, func_name, file_name='test.log'):
		self.func_name = func_name
		self.file_name = file_name
		
		
	def __call__(self,func):
		@wraps(func)
		def wappers(*args,**kw):
			if hasattr(self, self.func_name):
				my_func = getattr(self, self.func_name)
				if my_func(func):
					func(*args,**kw)
		return wappers
		
		
	def write_log(self,func):
		str_log = "{} funtion is runing".format(self.write_log.__name__)
		with open(self.file_name, 'a', encoding='utf-8') as f:
			f.write(str_log+'\n')
		return True
		
		
	def login_check(self,func):
		name = input("请输入用户名")
		pwd = input("请输入密码")
		if name == "albert" and pwd == "123":
			print ("log in success")
			return True
		else:
			print ("sorry, wrong username or password")
			return False
			
			
@Decorate('login_check')
@Decorate('write_log')
def print_func_name():
	print("I am a function named %s"%print_func_name.__name__)
	
	
def main():
	print_func_name()
	
	
if __name__ == "__main__":
	main()

在这里插入图片描述
在这里插入图片描述
当输入的用户名和密码与设置的不一致时,告知错误用户名或密码,然后不执行接下来的代码,当输入正确的时候,显示登入成功并且运行接下来的函数,记录运行日志,文件保存为test.log。
还可以做一个记录函数运行时间的装饰器,示例:

#使用装饰器实现 函数计时功能
import time
from functools import wraps


class Func_time(object):
	
	
	def __init__(self,name):
		self.name = name
		
		
	def __call__(self,func):
		@wraps(func)
		def wappers():
			start_time = time.time()
			func()
			time_diff = time.time() - start_time
			print("%s function run used %d s"%(func.__name__,time_diff))
		return wappers
		

@Func_time("timer")		
def run_func():
	print("start")
	time.sleep(3)
	print("end")
	
	
def main():
	run_func()
	
	
if __name__ == "__main__":
	main()

在这里插入图片描述
单独做一个程序运行日志记录的装饰器,示例:

#使用装饰器做一个日志记录
from functools import wraps


class Decorate():


	def __init__(self,file_name):
		self.file_name=file_name
		
	
	def __call__(self,func):
		@wraps(func)
		def wappers(*args,**kw):
			str_log="{} function is run".format(func.__name__)
			with open (self.file_name,'a',encoding="utf-8") as f:
				print(str_log)
				f.write(str_log+'\n')
			func(*args,**kw)
		return wappers
		
		
@Decorate("test.log")
def print_name(name,age):
	print("I am a function named %s"%print_name.__name__)
	print(f"my name is {name},my age is {age}")
	
	
def main():
	print_name("albert",23)
	
	
if __name__=="__main__":
	main()

在这里插入图片描述
在这里插入图片描述
当运行函数的时候,会自动生成该函数运行的日志。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值