一 有参装饰器
>带有参数的函数装饰器
为被装饰对象添加认证功能的装饰器,实现的基本形式如下
def deco(func):def wrapper(*args,**kwargs):编写基于文件的认证,认证通过则执行res=func(*args,**kwargs),并返回resreturn wrapper
如果想提供多种不同的认证方式以供选择,单从wrapper函数的实现角度改写如下
def auth(func,db_type):def wrapper(*args, **kwargs):name=input('your name>>>: ').strip()pwd=input('your password>>>: ').strip()if db_type == 'file':print('基于文件的验证')if name == 'egon' and pwd == '123':res = func(*args, **kwargs)return reselse:print('user or password error')elif db_type == 'mysql':print('基于mysql的验证')elif db_type == 'ldap':print('基于ldap的验证')else:print('不支持该db_type')return wrapper
函数wrapper需要一个driver参数,而函数deco与wrapper的参数都有其特定的功能,不能用来接受其他类别的参数,可以在deco的外部再包一层函数auth,用来专门接受额外的参数,这样便保证了在auth函数内无论多少层都可以引用到
def auth(db_type):def deco(func):def wrapper(*args, **kwargs):name = input('your name>>>: ').strip()pwd = input('your password>>>: ').strip()if db_type == 'file':print('基于文件的验证')if name == 'egon' and pwd == '123':res = func(*args, **kwargs) # index(1,2)return reselse:print('user or password error')elif db_type == 'mysql':print('基于mysql的验证')elif db_type == 'ldap':print('基于ldap的验证')else:print('不支持该db_type')return wrapperreturn deco
想要保留原函数的文档和函数名属性,需要修正装饰器
def timer(func):def wrapper(*args,**kwargs):start_time=time.time()res=func(*args,**kwargs)stop_time=time.time()print('run time is %s' %(stop_time-start_time))return reswrapper.__doc__=func.__doc__wrapper.__name__=func.__name__return wrapper
上述方式来实现保留原函数属性过于麻烦,functools模块下提供一个装饰器wraps专门用来
from functools import wrapsdef timer(func):@wraps(func)def wrapper(*args,**kwargs):start_time=time.time()res=func(*args,**kwargs)stop_time=time.time()print('run time is %s' %(stop_time-start_time))return resreturn wrapper
>带有参数的类装饰器
#参数1 : 给修饰的类添加成员属性和方法
#参数2 : 给类中的run方法变成属性class Kuozhan():ad = "我是属性"def char(self):print("我是方法")def __init__(self,num):self.num = numdef __call__(self,cls):print(cls)if self.num == 1:return self.kuozhan1(cls)elif self.num == 2:return self.kuozhan2(cls)#参数1的情况:添加成员属性和方法def kuozhan1(self,cls):def newfunc():cls.ad = Kuozhan.adcls.money = Kuozhan.moneyreturn cls()return newfunc#参数2的情况:把方法变成属性def kuozhan2(self,cls):def newfunc():if "run" in cls.__dict__:cls.run = cls.run()return cls()return newfunc
#
@Kuozhan(1)
class MyClass():def run():return "运动"
obj = MyClass()
print(obj.ad)
obj.money()#
@Kuozhan(2)
class MyClass():def run():return "运动"
obj = MyClass()
print(obj.run)
>property
可以把方法变成属性 : 可以动态的控制属性的获取,设置,删除相关操作
@property 获取属性
@方法名.setter 设置属性
@方法名.deleter 删除属性
class MyClass():def __init__(self,name):self.name = name@propertydef username(self):return self.name@username.setterdef username(self,val):self.name = valpass@username.delsterdef username(self):def self.namepass
obj = MyClass("小红")
获取指的时候自动触发@property 装饰器下的方法
res = obj.username
print(res)#设置值的时候自动触发@username.setter装饰器下的方法
obj.username = "小白"
print(obj.username)
class Myclass():def __init__(self,name):self.name = name #获取数据def get_username(self):return self.name#设置数据def set_username(self,val):self.name = val#删除数据def del_username(self):del self.name#参数的顺序:获取,设置,删除username = property(get_username, set_username, del_username)obj = MyClass("小白")
#获取值的时候,执行get_username下的相关操作
print(obj.username)
#设置值的时候,执行set_username下的相关操作
print(obj.username)
#删除值的时候,执行del_username下的相关操作
del obj.username
print(obj.username)
二 迭代器
1、什么是迭代器
迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复
都是基于上一次的结果而继续的,单纯的重复并不是迭代
2、为何要有迭代器
迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型
有:列表、字符串、元组、字典、集合、打开文件
l=['egon','liu','alex']i=0while i < len(l):print(l[i])i+=1
上述迭代取值的方式只适用于有索引的数据类型:列表、字符串、元组
为了解决基于索引迭代器取值的局限性
python必须提供一种能够不依赖于索引的取值方式,这就是迭代器
3、如何用迭代器
1、可迭代的对象
从语法形式上讲,内置有__iter__方法的对象都是可迭代对象,字符串、列表、元组、字典、集合、打开的文件都是可迭代对象
2、调用可迭代对象下的__iter__方法会将其转换成迭代器对象
3、可迭代对象与迭代器对象详解
可迭代对象("可以转换成迭代器的对象"):内置有__iter__方法对象
可迭代对象.__iter__(): 得到迭代器对象
迭代器对象:内置有__next__方法并且内置有__iter__方法的对象
迭代器对象.__next__():得到迭代器的下一个值
迭代器对象.__iter__():得到迭代器的本身
4、可迭代对象:字符串、列表、元组、字典、集合、文件对象
迭代器对象:文件对象
5、for循环的工作原理:for循环可以称之为叫迭代器循环,in后可以跟任意可迭代对象
1、d.__iter__()得到一个迭代器对象
2、迭代器对象.__next__()拿到一个返回值,然后将该返回值赋值给k
3、循环往复步骤2,直到抛出StopIteration异常for循环会捕捉异常然后结束循环
6、迭代器优缺点总结
6.1 优点:
I、为序列和非序列类型提供了一种统一的迭代取值方式。
II、惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。
6.2 缺点:
I、除非取尽,否则无法获取迭代器的长度
II、只能取下一个值,不能回到开始,更像是‘一次性的’,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。
三 生成器
如何得到自定义的迭代器:
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码
会返回一个生成器对象,生成器即自定义的迭代器
def func():print('第一次')yield 1print('第二次')yield 2print('第三次')yield 3print('第四次')触发函数体代码的运行,然后遇到yield停下来,将yield后的值
当做本次调用的结果返回
res1=g.__next__()
print(res1)