python 生成器、迭代器、动态新增属性及方法

目录

一、生成器

1、生成器定义

2、生成器存在的意义

3、创建生成器方式一(生成器表达式)

4. 创建生成器方式二(生成器函数)

1. 生成器函数

2. 生成器函数的工作原理

5. 总结

1. 什么是生成器

2. 生成器特点

二、迭代器

1、概念

2、可迭代对象和迭代器区别

 3、for循环本质

4、创建一个迭代器

三、动态添加属性和方法

1、动态编程语言定义

2、运行过程中给对象添加属性和方法

3、给类动态添加静态方法以及类方法

四、限制动态添加

1、slots

1.  __slots__的作用

2. 对动态添加成员变量、成员方法有限制

3. 对动态添加类属性、类方法没有限制


一、生成器

1、生成器定义

        在Python中,一边循环一边计算的机制,称为生成器:generator

2、生成器存在的意义

        列表所有数据都在内存中,如果有海量数据的话将会非常消耗内存。

        例如:仅需要访问前面几个元素,那后边所有空间就浪费了

        如果列表元素按照某种算法推算出来,就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的 list ,从而节省大量的空间。

3、创建生成器方式一(生成器表达式)

        生成器表达式很简单,只要把一个列表推导式的 [] 改成 () ,就创建了一个生成器(generator):

L = [x * x for x in range(10)]  #推导式
print(L)
g = (x * x for x in range(10)) #加成括号就是生成器
print(g)
#<generator object <genexpr> at 0x1022ef630>
'''L是一个list,而g则是一个 generator'''

4. 创建生成器方式二(生成器函数)

1. 生成器函数

  • 如果一个函数中包含了 yield 关键字,那么这个函数就不再是一个普通的函数,调用函数就是创建了一个生成器(generator)对象
  • 生成器函数:利用关键字 yield 一次性返回一个结果,阻塞,重新开始

2. 生成器函数的工作原理

  • 生成器函数返回一个迭代器,for循环对这个迭代器不断调用 __next__() 函数,不断运行到下一个 yield 语句,一次一次取得每一个返回值,直到没有 yield 语句为止,最终引发 StopIteration 异常
  •  yield 相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从 yield 下一条语句(不是下一行)开始执行
  •  send() next() 一样,都能让生成器往下走一步(下次遇到 yield 停),但 send() 能传一个值,这个值作为 yield 表达式整体的结果

测试生成器工作原理(yield)

'''
如果一个函数中包含 yield 关键字,那么这个函数就不再是一个普通函数,
调用函数就是创建了一个生成器(generator)对象

生成器函数:其实就是利用关键字 yield 一次性返回一个结果,阻塞,重新开始

原理
1. 函数有了yield之后,调用它,就会生成一个生成器
2. 下次从下一个语句执行,切记不是下一行(tmp = yield i)
3. return在生成器中代表生成器种植,直接报错:StopIeratation
4. next方法作用:唤醒并继续执行
'''
def test():
    print("start")
    i = 0
    while i<3:
        '''yield i #第一次执行,此处挂起;同时将i的值返回到i
                   #第二次执行,从挂起的地方往下执行'''
        temp = yield i #下次迭代时,代码从`yield`的下一条语句(不是下一行)开始执行
        print(f"i:{i}")
        i += 1
    print("end")
    return "done"
if __name__ == '__main__':
    a = test()
    print(type(a))
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())# 抛出异常:StopIteration
'''
<class 'generator'>
start
0
temp:None
1
temp:None
2
temp:None
end
Traceback (most recent call last):
 in <module>
    print(a.__next__())# 抛出异常:StopIteration
StopIteration: done
'''

测试生成器工作原理(send)

'''
send的作用是唤醒并继续执行,发送一个信息到生成器内部
'''
def foo():
    print("start")
    i = 0
    while i < 2:
        temp = yield i
        print(f"temp:{temp}")
        i += 1
    print("end")

g = foo()
print(next(g))  #等同g.__next__(),next是内置函数
print("*"*20)
print(g.send(100))
print(next(g))
# for a in g:#g所返回的值是yield处的i
#     print(a)
'''
start
0
********************
temp:100
1
temp:None
end
Traceback (most recent call last):
    print(next(g))
StopIteration
'''

5. 总结

1. 什么是生成器

        生成器仅仅保存了一套生成数值的算法,并且没有让这个算法现在就开始执行,而是我什么时候调用它,它什么时候开始计算一个新的值,并给你返回

2. 生成器特点

  •  生成器函数生成一系列结果。通过 yield 关键字返回一个值后,还能从其退出的地方继续运行,因此可以随时产生一系列的值。
  • 生成器和迭代是密切相关的,迭代器都有一个 __next__() 成员方法,这个方法要么返回迭代的下一项要么引起异常结束迭代
  • 生成器是一个特殊的程序,可以被用作控制循环的迭代行为,

二、迭代器

1、概念

  1. 迭代是Python最强大的功能之一,是访问集合元素的一种方式
  2. 迭代器是一个可以记住遍历的位置的对象
  3. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束
  4. 迭代器只能往前不会后退
  5. 迭代器有两个基本的方法: iter() netx() 

2、可迭代对象和迭代器区别

  1. 一个实现了 iter 方法的对象,称为 "可迭代对象 Ieratable"
  2. 一个实现了 next 方法并且是可迭代的对象,称为"迭代器" Iterator                                            即:实现了 iter 方法和 next 方法的对象就是迭代器

 生成器都是 Iterator对象,但 list dict str 虽然都是 Iterable(可迭代对象),              却不是Iterator(迭代器)

'''
生成器一定是迭代器
可迭代对象不一定是迭代器,使用iter([])封装后可转为迭代器
'''
from collections.abc import Iterator
from collections.abc import Iterable
a = isinstance([], Iterator) #list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器)
print(a)
a = isinstance([], Iterable) #可迭代对象
print(a)
"""
执行结果:
False
True

"""
'''list、dict、str 等 Iterable 变成 Iterator,可以使用 iter() 函数:'''
b = isinstance(iter([]), Iterator)
print(b)
b = isinstance(iter('花非人陌'), Iterator)
print(b)

"""
执行结果:
True
True
"""

        Python的 Iterator 对象表示的是一个数据流。可以把这个数据看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过 next() 函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。

        所以,生成器一定是迭代器

 3、for循环本质

#Python3 的 for 循环本质就是通过不断调用 next() 函数实现的。

for x in [1,2,3,4,5]:
    pass

'''本质是:'''
#首先获得Iterator对象:
it = iter([1,2,3,4,5])
#循环
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration 就退出循环
        break

4、创建一个迭代器

一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() __next__()

  1.  __iter__() 方法返回一个特殊的迭代器对象,这个迭代器对象实现了 __next__() 方法并通过StopIteration 异常标识迭代的完成
  2.  __next__() 方法会返回下一个迭代器对象
#创建一个依次返回10,20,30,...这样数字的迭代器
class MyNumbers:
    def __iter__(self):
        self.num = 10
        return self

    def __next__(self):
        if self.num < 40:
            x = self.num
            self.num += 10
            return x
        else:
            raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
"""
执行结果:
10
20
30
Traceback (most recent call last):
    raise StopIteration
StopIteration
"""
"""
程序解析:
在这段代码中,MyNumbers 类定义了一个迭代器。该迭代器的作用是生成一系列数字,从 10 开始,每次增加 10,直到 40,然后停止。

在程序中,通过 iter(myclass) 方法获取 MyNumbers 类的迭代器对象 myiter,然后调用 next(myiter) 方法获取下一个数字。

在第一次调用 next(myiter) 方法时,迭代器会执行 __next__() 方法,返回 self.num 的值 10,然后将 self.num 的值增加 10,变为 20。

在第二次、第三次调用 next(myiter) 方法时,迭代器会再次执行 __next__() 方法,返回 20 和 30,然后将 self.num 的值分别增加 10,变为 30 和 40。

在第四次调用 next(myiter) 方法时,迭代器再次执行 __next__() 方法,发现 self.num 的值已经大于等于 40,于是抛出 StopIteration 异常,表示迭代已经结束。
"""

三、动态添加属性和方法

1、动态编程语言定义

        指在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,

已有的函数可以被删除或是其他结构上的变化

2、运行过程中给对象添加属性和方法

#coding=utf-8
import types
class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person("zhangsan", 20)
p2 = Person("lisi", 18)
#动态给对象添加属性和方法
p1.score = 100
print(p1.score) #加给p1的只能p1用,对象的也是一样

#动态给对象添加方法
def run(self):
    print(f"{self.name}, running...")
p1.run = types.MethodType(run, p1)
#而types.MethodType(run,p1)则是告诉解释器,self指的就是p1
p1.run()
"""
执行结果:
100
zhangsan, running...
"""

3、给类动态添加静态方法以及类方法

#encoding=utf-8
class Person():
    __slots__ = {"name", "age"}
    def __init__(self, name, age):
        self.name = name
        self.age = age

@staticmethod
def staticfunc():
    print("--- static method ---")

Person.staticfunc = staticfunc
Person.staticfunc()
Person.score = 1000 #动态给对象静态方法
print(Person.score)

@classmethod
def clsfunc(cls):
    print('--- cls method ---')
Person.clsfunc = clsfunc    #动态增加类方法
Person.clsfunc()

四、限制动态添加

1、slots

1.  __slots__的作用

  1. __slots__ 对动态添加成员变量、成员方法有限制。对动态添加类属性、类方法没有限制
  2. __slots__ 只对本类有限制,不限制子类

2. 对动态添加成员变量、成员方法有限制

'''
MyClass 类使用 __slots__ 属性限制了实例对象的属性,只允许动态添加 x 属性。
因此,obj.x = 1 可以成功,但是 obj.y = 2 会抛出 AttributeError 异常
'''
class MyClass:
    __slots__ = ['x']


obj = MyClass()
obj.x = 1  # 可以动态添加 x 属性
obj.y = 2  # 报错,__slots__ 限制了不能动态添加 y 属性
"""
执行结果:
AttributeError: 'MyClass' object has no attribute 'y'
"""

3. 对动态添加类属性、类方法没有限制

class MyClass:
    __slots__ = ['x']
    classattr = 1

    @classmethod
    def myclassmethod(cls):
        print("class method")


MyClass.newclassattr = 2  # 可以动态添加类属性
print(MyClass.newclassattr)
MyClass.mynewclassmethod = lambda cls: print("new class method")  # 可以动态添加类方法
MyClass.mynewclassmethod(MyClass)   #传递类本身作为参数
obj = MyClass()
obj.x  = 3    # 可以动态添加实例属性
print(obj.x)  # 可以动态添加 x 属性
"""
执行结果:
2
new class method
3
"""

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/7450.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

365天深度学习训练营-第J8周:Inception v1算法实战与解析

目录 一、前言 二、论文解读 1. Inception 模块 2. 网络深度问题 3. 全局平均池化 4. 卷积层的并行结构 5. 1x1 卷积核 6.详细的网络结构 三、代码复现 一、前言 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#x…

微服务+springcloud+springcloud alibaba学习笔记【Eureka服务注册中心】(3/9)

Eureka服务注册中心 3/91、服务注册与发现1.1 什么是服务治理&#xff1a;1.2 什么是服务注册与发现&#xff1a;1.3 Eureka服务注册与发现2、单机版eureka2.1 创建module2.2改pom依赖2.3写yml配置文件:2.4主启动类2.5 修改服务提供者 cloud-provider-payment8001 模块&#xf…

Github库中的Languages显示与修改

目录 前言 【.gitattributes】文件 修改GitHub语言 前言 上传一个项目到GitHub时&#xff0c;发现显示的语言并非是自己项目所示的语言&#xff0c;这样的情况是经常发生的&#xff0c;为了能到达自己所需快速检索&#xff0c;或者是外部访问者能很好的搜索我们的项目&#…

Sentinel滑动时间窗限流算法原理及源码解析(中)

文章目录 MetricBucketMetricEvent数据统计的维度WindowWrap样本窗口实例 范型T为MetricBucket windowLengthInMs 样本窗口长度 windowStart 样本窗口的起始时间戳 value 当前样本窗口的统计数据 其类型为MetricBucket MetricBucket MetricEvent数据统计的维度 1、首先计算27t位…

【花雕学AI】09:发挥ChatGPT最大潜力——产生高质量内容的九种方法和建议

人工智能&#xff08;AI&#xff09;是当今科技领域最热门和最有前景的话题之一&#xff0c;它已经渗透到了我们生活和工作的方方面面&#xff0c;给我们带来了许多便利和惊喜。而在AI的众多分支中&#xff0c;自然语言处理&#xff08;NLP&#xff09;是最贴近人类的一个领域&…

6-python异常、错误、模块、包

文章目录1.异常2.错误3.模块4.包[综合练习]1.异常 打开一个不存在的文件会引发异常 FileNotFoundError: [Errno 2] No such file or directory: ‘D:/不存在的文件.txt’ fopen(file"D:/不存在的文件.txt",mode"r", encodingutf-8) print(f.read())&…

springboot-gateway注册nacos失败,控制台没有报错

目录 前言现象描述前言 最近springboot的gateway注册到nacos上,没有注册成功 现象描述 我是在common里面引入了nacos的依赖,依赖如下: <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-confi…

文件的随机读写

fseek fseek这个函数的作用是什么&#xff1f; 我们知道&#xff0c;如果对一个文件指针进行加减操作的话&#xff0c;这个文件指针会指向下一个文件&#xff0c;那么问题来了&#xff0c;我们如果想访问这个文件中的某一个内容&#xff0c;这个时候该怎么办呢&#xff0c;我们…

基于支持向量机SVM的脑部肿瘤识别,脑电波样本熵提取

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 SVM应用实例,基于SVM的的脑部肿瘤识别分类预测 代码 结果分析 展望 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它…

下一代的新操作系统就是ChatGPT!

什么是CHatgpt&#xff1f; ChatGPT是人工智能研究实验室OpenAI在2022年11月30日推出的聊天机器人模型&#xff0c;它使用Transformer神经网络架构&#xff0c;训练数据来自包括维基百科&#xff0c;以及真实对话在内的庞大语料库。2023年1月30日消息称&#xff0c;中国搜索巨…

数据分析-统计基础

day1&#xff1a;集中趋势&#xff0c;离散测度&#xff0c;均值&#xff0c;中位数&#xff0c;众数&#xff0c;方差等。点估计&#xff0c;区间估计等相关的知识 现代数据分析&#xff1a;把数据放到一个数据空间中&#xff0c;通过这个空间的个各种形变与分析而挖掘除数据…

Android RenderScript 浅谈

前言 RenderScript是一个Google出品的&#xff0c;在Android平台上的并行计算框架&#xff0c;官方的简介是说RenderScript运行时可在设备上提供的多个处理器&#xff08;如多核 CPU 和 GPU&#xff09;间并行调度工作。在日常Android开发中&#xff0c;RenderScript主要用于图…

数据库:Redis哨兵及cluster集群部署

一、redis数据库哨兵模式 目录 一、redis数据库哨兵模式 1、什么是哨兵模式 2、哨兵的作用 3、哨兵结构组成 4、哨兵故障转移机制 5、哨兵工作、切换原理 6、哨兵主节点选举原则 7、哨兵模式部署 二、redis数据库cluster集群 1、cluster集群优点、数据存储及同步方式…

Chapter2 : SpringBoot配置

尚硅谷SpringBoot顶尖教程 1. 全局配置文件 SpringBoot使用一个全局的配置文件 application.properties 或者 application.yml &#xff0c;该配置文件放在src/main/resources目录或者类路径/config目录下面&#xff0c; 可以用来修改SpringBoot自动配置的默认值。 yml是YA…

wxml模板,wxss模版,全局配置,页面配置,网络数据请求

WXML 模板语法 1、数据绑定 1.1、数据绑定的基本原则 ① 在 data 中定义数据② 在 WXML 中使用数据 1.2、在 data 中定义页面的数据 在页面对应的 .js 文件中&#xff0c;把数据定义到 data 对象中即可&#xff1a; Page({data: {//字符串数据info:init data}, });1.3、M…

《Kubernetes部署篇:Ubuntu20.04基于containerd部署kubernetes1.24.12单master集群》

一、架构图 如下图所示&#xff1a; 二、环境信息 主机名K8S版本系统版本内核版本IP地址备注k8s-master-621.24.12Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.62master节点k8s-worker-631.24.12Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.63worker节点k8s-worker-641…

二、SDN-计算机网络专项(2)

1、编码 编码形式&#xff1a; 以太网使用的编码方式为曼彻斯特编码。 2、信息传输速率 &#xff08;1&#xff09;香农定理 带宽为W&#xff08;Hz&#xff09;且有高斯噪音干扰&#xff08;信噪比S/N&#xff09;的信道极限信息传输速率为&#xff1a; 还有&#xff0c;信噪…

Linux_红帽8学习笔记分享_2

Linux_红帽8学习笔记分享_2 文章目录Linux_红帽8学习笔记分享_21.远程控制servera和serverb1.1开启多标签页1.2启用servera和serverb1.3连接servera和serverb2.退出子虚拟机并关机2.1退出子虚拟机2.2关闭虚拟机2.3重启虚拟机3.Linux在使用过程中遇到的基础操作3.1退出至登录界面…

Spring销毁的几种实现

有这3种方法&#xff0c;但是程序执行完成并没有打印出来。一定要手动close.手动执行后会调用如下逻辑&#xff1a;org.springframework.context.support.AbstractApplicationContext#doCloseorg.springframework.context.support.AbstractApplicationContext#destroyBeansorg.…

点亮孙武不夜城 拉响惠民经济新引擎

凡战者&#xff0c;以奇制胜。这次的招商很特别—孙武不夜城招商项目正式启动&#xff01;      无租金、无投资、无风险合伙人制。      现诚邀广大商家合作&#xff0c;相聚不夜城。同此道者&#xff0c;合大志&#xff0c;鸣鼓纳征&#xff0c;亮惠民夜生活&#xf…
最新文章