四大器
四大器
目录
- 一、迭代器
- 二、生成器
- 三、装饰器
- 四、内置装饰器(绑定方法)
- 绑定方法
一、迭代器
迭代器:迭代取值的工具 ——(用__iter__生成迭代器对象)
优点:1.不依赖与索引取值
2.内存中只占一份空间,不会内存溢出,节约空间,运行效率更高(执行一次__next__取值一次,而不是一次全部取值)
缺点:1.不能获取指定的元素
2.只能依次往后取值
1.迭代协议
class MyIter:
"""num传入 用来指定迭代次数 """
def __init__(self, num):
self.num = num
self.c = 0
# 迭代
def __iter__(self):
return self
# 取值
def __next__(self):
self.c += 1
if 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, 3
print('第二次')
yield 2
print('第三次')
yield 3
print('第四次')
yield
yield
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'] = user
print('登录成功')
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('请输入数字')
continue
msg = {'1': register,
'2': login,
'3': lookup}
msg[choice]()
run()
2.有参模板(三层)
# 有参模板
from functools import wraps
def wrappers(params1,params2,params3):
def outter(func):
@wraps(func)
def inner(*args, **kwargs):
# 装饰前做的事
return func(*args, **kwargs)
# 装饰后做的事
return inner
return 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 = name
self.__age = age
@property # 获取属性时,触发下面
# 获取伪装成普通属性,通常函数名伪装成属性名
def age(self):
return self.__age
@age.setter # 修改属性时,触发下面
def age(self, new_age):
self.__age = new_age
print('修改成功')
@age.deleter # 删除属性时,触发下面
def age(self):
del self.__age
print('删除成功,已经没有了')
# 查看
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 = name
self.age = age
self.sex = gender
def 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 = user
self.pwd = pwd
self.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:
@staticmethod
def func(res):
print(res)
# 产生了obj对象
obj = Foo()
obj.func(123) # 123
3.类直接调用非绑定方法
class Foo:
@staticmethod
def func(res):
print(res)
Foo.func(1234)
# 1234