四大器
目录
- 一、迭代器
- 1.迭代协议
- 2.一个简单的迭代器:
- 3.迭代异常处理(迭代完了,没有了,try)
- 二、生成器
- yield与return的区别:
- 三、装饰器
- 1.无参模板(二层)
- 2.有参模板(三层)
- 四、内置装饰器(绑定方法)
- 1.@property内置装饰器
- 绑定方法
- 1.对象绑定方法
- 2.类的绑定方法@classmethod
- 3.非绑定方法@staticmethod
一、迭代器
迭代器:迭代取值的工具 ——(用__iter__生成迭代器对象)
优点:1.不依赖与索引取值
2.内存中只占一份空间,不会内存溢出,节约空间,运行效率更高*(执行一次__next__取值一次,而不是一次全部取值)*
缺点:1.不能获取指定的元素
2.只能依次往后取值
1.迭代协议
class MyIter:"""num传入 用来指定迭代次数 """def __init__(self, num):self.num = numself.c = 0# 迭代def __iter__(self):return self# 取值def __next__(self):self.c += 1if self.c <= self.num:return "jeff"else:raise StopIteration# 循环取值
for i in MyIter(10):print(i)#结果:打印10遍jeff
2.一个简单的迭代器:
k = [1, 2, 3]
# 生成迭代器对象
k1 = k.__iter__()
#迭代器取值,调用__next__()
print(k1.__next__())
print(k1.__next__())
print(k1.__next__())
3.迭代异常处理(迭代完了,没有了,try)
k = [1,2,3]
k1 = k.__iter__()while True:try:print(k1.__next__())except StopIteration:print("没有了")break
二、生成器
优点:节约内存,不会内存溢出
生成器:使用yield自定义的迭代器叫生成器
yield:
1.后面不跟值,默认返回None,可以返回多个值
2.帮你将函数的运行状态暂停住
3.可以返回值,多个也可以
yield与return的区别:
1.yield配合迭代器使用__next__一个一个取值,return一次性全取
2.yield可以返回多次值,return返回一次立即结束函数
3.yield可以接受外部传入的值
def func():print("first")yield 1, 2, 3 # 函数内如果有yield,执行函数时不会执行函数代码k = func() # 将函数转化为迭代器
k2 = k.__next__() # 取值
print(k2)
要一次,取一次值
def func():print('第一次')yield 1, 2, 3print('第二次')yield 2print('第三次')yield 3print('第四次')yieldyield
k = func() # 转化为迭代器
# k1 = k.__iter__() # 这里不用生成迭代对象,函数自身可被迭代
print(k.__next__())
print(k.__next__())
print(k.__next__())
print(k.__next__())
三、装饰器
定义:不改变函数的源代码、调用方式,添加新的功能
1.无参模板(二层)
from functools import wraps # 语法糖def outter(func): # 固定搭配@wraps(func) # 固定搭配 语法糖def inner(*args, **kwargs): # 固定搭配# 装饰前做的事return func(*args, **kwargs) # 固定搭配# 装饰后做的事return inner # 固定搭配
例子:给lookup添加登录认证的功能
user_info = {'user':None
}def login():user = input('请输入用户名>>>:')passwd = input('请输入密码>>>:')passwd_d = input('请再次输入密码>>>:')if passwd == passwd_d:user_info['user'] = userprint('登录成功')else:print('登录失败')def register():user = input('请输入用户名>>>:')passwd = input('请输入密码>>>:')passwd_d = input('请再次输入密码>>>:')if passwd == passwd_d:with open(r'user', 'w')as f:f.write(user)f.write(passwd)else:print('重新输入')# 装饰器
def outter(func):def inner(*args, **kwargs):if user_info['user']:print('hello')return func(*args, **kwargs)else:print('请先登录')login() # 添加login的功能return inner@outter
def lookup():with open(r'user','r')as f:print(f.read())def run():while True:print('''
请选择你的功能>>>:
1.注册
2.登录
3.查看信息''')choice = input('>>>:')if not choice.isdigit():print('请输入数字')continuemsg = {'1': register,'2': login,'3': lookup}msg[choice]()run()
2.有参模板(三层)
# 有参模板
from functools import wrapsdef wrappers(params1,params2,params3):def outter(func):@wraps(func)def inner(*args, **kwargs):# 装饰前做的事return func(*args, **kwargs)# 装饰后做的事return innerreturn outter
四、内置装饰器(绑定方法)
1.@property内置装饰器
夺命三问:1.什么是property?是一个python内置的装饰器,可以装饰在"类内部的方法"上。可以将该方法调用方式由 ----> 对象.方法() ---> 对象.方法2.为什么用property?PS: 在某些场景下,调用的方法只是用来获取计算后的某个值。PS: 必须通过 对象.方法() 方式调用,让该方法看起来像执行函数。让名词的方法,调用时更为合理。目的是为了,迷惑调用者,调用的方法误以为是 属性。
装饰器:为了调用方式一致,方便使用者
@property首先创建一个age对象,所以@setter、@deleter要加函数名
:这里的age是装饰方法的名称
@property(获取私有) :把一个方法伪装成普通属性,通常函数名和属性名保持一致(方便使用者调用)
@函数名.setter(修改私有):函数名和属性名保持一致
@函数名.deleter(控制删除):
class A:def __init__(self, name, age):self.name = nameself.__age = age@property # 获取属性时,触发下面# 获取伪装成普通属性,通常函数名伪装成属性名def age(self):return self.__age@age.setter # 修改属性时,触发下面def age(self, new_age):self.__age = new_ageprint('修改成功')@age.deleter # 删除属性时,触发下面def age(self):del self.__ageprint('删除成功,已经没有了')
# 查看
jeff = A('jeff', 50)
print(jeff.age) # 50# 修改
jeff.age = '100'
print(jeff.age) # 修改成功 100# 删除
del jeff.age
print(jeff.age) # 报错,删除成功,已经没有了
绑定方法
classmethod:是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。staticmethod:翻译: 静态方法是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。- 对象的绑定方法:- 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。- 类的绑定方法:- 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。- 非绑定方法:- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
1.对象绑定方法
没有被任何装饰器装饰的方法,为对象量身定制
对象.方法(),自动将对象单座第一个参数传入self
class OldboyStudent:school = 'oldboy'def __init__(self, name, age, gender):self.name = nameself.age = ageself.sex = genderdef choose_course(self):print(f'{self.name} choosing course')def func(self):print('from func')stu1 = OldboyStudent('nick', 18, 'male')
stu2 = OldboyStudent('sean', 17, 'male')
stu3 = OldboyStudent('tank', 19, 'female')print(stu1.name) # nick
print(stu1.school) # oldboy
2.类的绑定方法@classmethod
classmethod:是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。
例子:
class Dog():def eat(self):print('狗狗吃饭饭。。。')class Pig():@classmethod # 将此方法对象绑定def eat(self):print('猪猪看电视。。。')# 对象绑定方法,需要实例化出一个对象
keji = Dog()
keji.eat()# 类绑定方法,不需要对象,直接通过类
zhu = Pig.eat()
例子2:进阶高级
class DB:__data = 'jeff is very handsome!!!'def __init__(self, user, pwd, role):self.user = userself.pwd = pwdself.role = role# 查看数据方法@classmethod # 类绑定def check_db(cls, user, pwd, role): # cls --》指的是类# 在类方法内部调用类产生一个实例 ---》 对象obj = cls(user, pwd, role) # 再类的内部实例化出一个对象,供内部使用# 1.查看数据前,必须要通过校验if obj.user == 'tank' and obj.pwd == '123' and obj.role == 'admin':print('检验通过..')print(cls.__data)return cls.__data# 类绑定方法了
DB.check_db('tank', '123', 'admin')
# 结果:
检验通过..
jeff is very handsome!!!
3.非绑定方法@staticmethod
非绑定方法:- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
1.不用非绑定方法,打印的是func函数的地址
class Foo:def func(res):print(res)
obj = Foo()
obj.func()
# <__main__.Foo object at 0x000001FF9F5D82E8>2.对象调用非绑定方法
class Foo:@staticmethoddef func(res):print(res)
# 产生了obj对象
obj = Foo()
obj.func(123) # 1233.类直接调用非绑定方法
class Foo:@staticmethoddef func(res):print(res)
Foo.func(1234)
# 1234