7. 迭代器生成器和Property属性
1. 迭代器①定义自定义的类只要重写了__iter__()和__next__()方法就可以称为迭代器惰性加载用的时候才会获取.②目的隐藏底层的逻辑让用户使用更方便。2.生成器①定义根据程序员制定的规则循环生成数据当条件不成立时则生成数据结束。数据不是一次性全部生成出来而是使用一个再生成一个可以节约内存。②创建方式生成器推导式和yield关键字方式一生成器推导式。语法例如生成器名(i * 2 for i in range(5))next()获取生成器中的下一个值;for循环遍历生成器中的每一个值;#1.创建生成器my_generator(i*2foriinrange(5))print(my_generator)#2.next获取生成器下一个值valuenext(my_generator)print(value)#3.遍历生成器forvalueinmy_generator:print(value)#注意:创建生成器时括号()代表这是一个生成器不是元组#括号()里面写的是数据的生成规则返回一个对象对象内不是存的数据而是产生数据的规则方式二yield 关键字。语法只要在def函数里面看到有yield关键字那么就是生成器;defmy_generater(n):foriinrange(n):print(开始生成...)yieldiprint(完成一次...)if__name____main__:gmy_generater(2)# 获取生成器中下一个值# result next(g)# print (result)# for遍历生成器for循环内部自动处理了停止迭代异常使用起来更加方便foriing:print(i) 案例1演示生成器之 推导式写法 importsys#system 系统模块# 需求1: 生成1-10之间的整数my_generator(iforiinrange(1,11))print(my_generator)#运行结果generator object genexpr at 0x102939820print(type(my_generator))#运行结果class generator# 需求2: 生成1-10之间的偶数my_generator2(iforiinrange(1,11)ifi%20)print(my_generator2)#运行结果generator object genexpr at 0x102ff1890# 需求3: 如何从生成中获取数据print(next(my_generator2))#运行结果2print(next(my_generator2))#运行结果4foriinmy_generator2:print(i)#运行结果6 8 10# 需求4验证生成器是可以减少内存占用数据多的时候明显因为数据少的时候生成器本身也占内存list[iforiinrange(10000000)]generator(iforiinrange(10000000))print(type(list))#运行结果class listprint(type(generator))#运行结果class generator# 查看内存空间占用print(flist的内存占用{sys.getsizeof(list)})#运行结果89095160print(fgenerator的内存占用{sys.getsizeof(generator)})#运行结果112 案例2演示生成器之 yield方式 importsys#system 系统模块# 需求1: 通过yield方式生成1-10之间的整数# 方式一推导式写法my_generator(iforiinrange(1,11))# 方式二yield方式# 1.定义函数存储到生成器中并返回defmy_func():# list[] #创建# for i in range(1,11):# list.append(i) #添加# return list #返回# yield方式效果类似上面的代码# yield此处做了三件事1.创建生成器对象2.把值存储到生成器中3.返回生成器foriinrange(1,11):yieldi# 2.测试generatormy_func()print(type(generator))#运行结果class generatorprint(next(generator))#运行结果1print(next(generator))#运行结果2print(**32)foriingenerator:print(i)#运行结果3 4 5 6 7 8 9 103. Property属性定义负责把一个方法当做属性进行使用这样做可以简化代码使用定义property属性有两种方式① 装饰器方式② 类属性方式。方式一装饰器方式。语法property修饰获取值的方法方法名.setter修饰设置值的方法。classPerson(object):def_init(self):self._age0#获取属性propertydefage(self):returnself._age# 修改属性age.setterdefage(self,new_age):self._agenew_ageif__name____main__:personPerson()print(person.age)person.age100print(person.age)代码 案例:演示property属性的用法. property属性介绍: 概述/目的/作用: 把函数当做变量来使用。 实现方式: 方式1:装饰器. 方式2:类属性. property的装饰器用法: property 修饰获取值的函数 获取值的函数名.setter 修饰设置值的函数 之后就可以直接.上述的函数名来当做变量直接用 #需求:定义学生类私有属性age通过property实现简化调用.#1.定义学生类。classStudent:# 1.1 私有属性def__init__(self):self.__age18# 1.2 提供公共的访问方式property# def get_age(self):defage(self):returnself.__age# get_age.setter# def set_age(self, age): # 这里可以做检验但一般不做除非重要字段才做二次校验age.setterdefage(self,age):#这里可以做检验但一般不做除非重要字段才做二次校验self.__ageage# 2.测试if__name____main__:#2.1 创建学生对象studentStudent()# 2.2 设置值并获取值# 方式一传统获取方式函数方法# student.set_age(10)# print(student.get_age()) # 运行结果10# 方式二使用Property属性把# 即在类的get方法上加上propertyset方法上加上方法名.setter# 实际开发中直接用age不用set_age、get_age# student.set_age10# print(student.get_age) # 运行结果10student.age10print(student.age)# 运行结果10方式二类属性方式。语法即类属性property(获取值方法设置值方法)两参数位置不能换先获取在设置此时下面的get_age、set_age不能和方式一那样 两者改名相同都改为ageclassPerson(object):def_init_(self):self._age0defget_age(self):#3当获取age属性的时候会执行该方法returnself._agedefset_age(self,new_age):# 当设置age属性的时候会执行该方法self._agenew_age#类属性方式的property属性ageproperty(get_age,set_age)if__name____main__:personPerson()print(person.age)person.age100print(person.age)代码 案例:演示property属性的用法. property属性介绍: 概述/目的/作用: 把函数当做变量来使用。 实现方式: 方式1:装饰器. 方式2:类属性. property的装饰器用法: property 修饰获取值的函数 获取值的函数名.setter 修饰设置值的函数 property的类属性的用法: 类属性名property(获取值的函数名, 设置值的函数名) 之后就可以直接.上述的函数名来当做变量直接用 #需求:定义学生类私有属性age通过property充当类属性用#1.定义学生类。classStudent:# 1.1 私有属性def__init__(self):self.__age18# 1.2 提供公共的访问方式defget_age(self):returnself.__agedefset_age(self,age):# 这里可以做检验但一般不做除非重要字段才做二次校验self.__ageage# 1.3 封装上述的公共方式为类属性ageproperty(get_age,set_age)# 2.测试if__name____main__:#2.1 创建学生对象studentStudent()# 2.2 设置值并获取值student.age10print(student.age)# 运行结果10