鱼C论坛

 找回密码
 立即注册
楼主: wideband

类学习

[复制链接]
 楼主| 发表于 2023-6-17 08:05:23 | 显示全部楼层
关于  迭代器:
class MyList():
    def __init__(self):
        self.container = []
    def add(self,item):
        self.container.append(item)


mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)

for i in mylist.container:# for i in mylist:
    print(i)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-17 08:33:41 | 显示全部楼层
迭代器:

my_list 是一个列表对象,但它也是一个可迭代对象。当我们使用 for 循环遍历它时,Python 会自动调用 iter(my_list) 获取一个迭代器,并通过该迭代器逐个访问列表中的元素。每次迭代都会重新获取一个新的迭代器对象,并从列表的第一个元素开始遍历。
my_list = [1, 2, 3]
for item in my_list:
    print(item)

对可迭代对象进行迭代使用的过程,发现每迭代一次(即在for...in...中每循环一次)都会返回对象中的下一条数据(还是步长为2),一直向后读取数据直到迭代了所有数据后结束。

在这个过程中就应该有一个“人”去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据。我们把这个能帮助我们进行数据迭代的“人”称为迭代器(Iterator),就是规则。可迭代对象的本质就是可以向我们提供一个这样的中间“人。


列表(list)不是迭代器对象,但它是一个可迭代对象(Iterable)。可迭代对象指的是具有 __iter__() 方法的任何对象,该方法返回一个迭代器对象(Iterator)。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-17 08:56:48 | 显示全部楼层
一个实现了 __ter__(记录访问到第几条数据), 和 __next__方法(下几个数据的规则)的对象,就是迭代器
输出:
1
2
3
4
5
class MyList(object):
    """自定义的一个可迭代对象"""

    def __init__(self):
        self.items = []

    def add(self, val):
        self.items.append(val)

    def __iter__(self):
        myiterator = MyIterator(self)
        return myiterator


class MyIterator(object):
    """自定义的供上面可迭代对象使用的一个迭代器"""

    def __init__(self, mylist):
        self.mylist = mylist
        # current用来记录当前访问到的位置
        self.current = 0

    def __next__(self):
        if self.current < len(self.mylist.items):
            item = self.mylist.items[self.current]
            self.current += 1
            return item
        else:
            raise StopIteration

    def __iter__(self):
        return self


if __name__ == '__main__':
    mylist = MyList()
    mylist.add(1)
    mylist.add(2)
    mylist.add(3)
    mylist.add(4)
    mylist.add(5)
    for num in mylist:
        print(num)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-18 22:22:01 | 显示全部楼层
对数列来说,此数量是可迭代对象(数据固定),去1个,是个迭代器,再去一个,又是个迭代器.......器,很多碗 叠在一起。 可迭代对象,就是 最大一个。迭代器就像一把钥匙,它可以打开一个房间的所有门,让我们逐一浏览房间内的每一个角落,而不需要提前知道所有的门和房间位置。

obj_iter = [1,2,3,4,5,6,7,8,9]
#obj_iter可迭代对象, obj_next迭代器
obj_next = obj_iter.__iter__()

print(obj_next.__next__()) # 迭代器obj_next被取走了一个1
print(obj_next.__next__()) # 迭代器obj_next被取走了一个2
for i in obj_iter:         # 是一个全新的迭代器
    print(i)
# 之前被取掉了 1,2 这2个数据        ohj_next剩下3,4,5,6,7,8,9
for i in obj_next:
    print(i)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-19 07:17:29 | 显示全部楼层
虽然MyList类和MyIterator类之间存在循环依赖,但是它们之间的交互都是在合理的范围内进行的,并没有出现具体的问题。实际上,很多Python的库和框架中都存在着循环依赖关系,但是大多数情况下并不会出现错误,这主要是因为Python有一个很强的模块系统和垃圾回收机制,可以帮助程序处理这样的依赖关系。

但是,循环依赖仍然不是一个好的设计,它可能会导致代码的可读性和可维护性降低,也会增加程序出错的可能性。因此,在编写代码时,我们尽量要避免循环依赖的出现。

优化:
class MyList:
    def __init__(self, data):
        self.data = data
        
    def __iter__(self):
        return MyIterator(self.data)
    
class MyIterator:
    def __init__(self, data):
        self.index = 0
        self.data = data
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

data = [1, 2, 3, 4, 5]
mylist = MyList(data)

for num in mylist:
    print(num)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-19 09:37:33 | 显示全部楼层
闭包: 嵌套函数,内部函数,使用 外部函数传递的 参数(变量)

def outer(a):
     def inner(b):
           xxxx
     return inner

调用:a<1, b<2

outer(1)(2)   x   或者建议格式:   

f = outer(1)
f(2)



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-19 09:49:49 | 显示全部楼层
//www.bilibili.com/video/BV1qW4y1a7fU?p=155&vd_source=bbd2966da727b3376515872084138922
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-19 10:27:04 | 显示全部楼层
可迭代对象,使用__iter__成为  迭代器 :  iter(my_list), 具备了 next 方法;

生成器也是一种迭代器,但是它是一个使用了yield关键字的函数,记得了 上一次返回时,在f 中的位。每执行到yield语句,函数会将yield后面的表达式计算出来并返回,并保存当前函数的状态。下次调用生成器的__next__()方法时,函数会从上一次离开的地方继续执行,直到遇到下一个yield语句或者函数结束。这种能够暂停和恢复执行状态的特性使得生成器可以逐个产生计算结果,而不需要事先把所有结果都计算出来,从而节省了内存空间和计算时间。
def my_generator(data):
    for item in data:
        yield item

my_list = [1, 2, 3, 4, 5]
my_gen = my_generator(my_list)

print(next(my_gen))  # 输出: 1
print(next(my_gen))  # 输出: 2
print(next(my_gen))  # 输出: 3


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-21 08:39:21 | 显示全部楼层
_getitem__() 是 Python 中的一种特殊方法,用于支持对象的索引访问。成为 序列对象

class MyList:
    def __init__(self, data):
        self.data = data

    def __getitem__(self, idx):
        return self.data[idx]
这样,我们就可以使用类似列表的方式来访问 MyList 中的元素,比如:

>>> mylist = MyList([1, 2, 3, 4, 5])
>>> mylist[0]
1
>>> mylist[2:4]
[3, 4]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-21 09:28:42 | 显示全部楼层
迭代器,是定义了迭代方式的一种数据模型,比如多个跌放在一起的 正方形木框:回 字形状,取最里面的一个,就可以知道靠近最里面的下一个。
也可以说是实现了:__iter__ 和 __next__
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-21 09:42:24 | 显示全部楼层
为什么下边代码有错误提示:TypeError: iter() returned non-iterator of type 'NoneType'
class Student:
    def __iter__(self):
        pass

stu = Student()

for i in stu:
    pass

Python 的规定,实现了 __iter__() 方法的对象必须返回一个迭代器对象。由于 __iter__() 方法中的代码只有一个 pass 语句,没有显式地返回任何值,因此默认返回值为 None。而由于 None 不是迭代器,需要在 __iter__() 方法中返回一个迭代器对象。
class Student:
    def __init__(self):
        self.names = ['Alice', 'Bob', 'Charlie']
    
    def __iter__(self):
        return iter(self.names)

stu = Student()

for name in stu:
    print(name)

__iter__() 方法返回了 iter(self.names),也就是将列表 self.names 转换成迭代器后返回。这样,在 for 循环中遍历 stu 对象时,就可以逐个输出列表中的元素了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-22 11:02:12 | 显示全部楼层
装饰器
//www.bilibili.com/video/BV1qW4y1a7fU?p=155&vd_source=bbd2966da727b3376515872084138922

def outer(func):
     def inner():
     ....
     return inner

fn = outer(sleep)——调用outer,返回inner引用
fn()——调用inner
import random
import time

def outer(func):
    def inner():
        print("我要睡觉了......")
        func()
        print("我要起床了......")
    return inner


def sleep():
    print("睡眠中......")
    time.sleep(random.randint(1,5))


fn = outer(sleep)
fn()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-23 09:59:33 | 显示全部楼层
装饰器 带有参数:
def bug_level(level):
    def outer(function):
        def inner(*args, **kwargs):
            print(f'bug等级 -[{level}]:运行的函数名为:{function.__name__}')
            function(*args, **kwargs)
        return inner
    return outer

@bug_level('info')
def say(name, message):
    print(f'{name}:{message}')

say('张三','工作认真...')
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-23 11:32:12 | 显示全部楼层
基于类的装饰器:
class Logging:
    def __init__(self, func_obj):
        self.func_obj=func_obj

    def __call__(self, *args, **kwargs):
        print(f'debug:调用的函数名为 - {self.func_obj.__name__}')
        self.func_obj(*args, **kwargs)

# @Logging
def say(name, message):
    print(f'{name}:{message}')

#say('张三','工作认真负责..')

cls_obj = Logging(say)
cls_obj('张三','工作认真负责...')
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-24 15:03:20 | 显示全部楼层
创建多个线程对象:

t1=threading.Thread(target=get_image,args=(url,))
t1.start()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-24 16:35:23 | 显示全部楼层
函数入口 和 特殊的内置变量 __name__
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-24 20:41:44 | 显示全部楼层
并发:一个时间段内,多个任务一起执行,给人的感觉是任务在同时执行,但实际上是通过时间片轮转或事件驱动等机制来实现的。并发常用于解决多个任务之间的交互、并发访问共享资源等问题,提高系统的吞吐量和响应性。典型的并发编程模型包括多线程和协程。



并行:一个时间点内,多个任务一起执行,在并行模型下,多个处理单元(如多个 CPU 核心)可以独立地执行任务,每个处理单元处理自己的任务集合,相互之间不需要切换或等待。并行通常用于高性能计算、数据并行处理等领域,能够显著减少任务的执行时间。典型的并行编程模型包括多进程和向量化计算。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-29 17:53:54 | 显示全部楼层
使用类来创建线程对象,

定义了一个名为 MyThread 的线程类,继承自 threading.Thread。在 run() 方法中,我们定义了线程的具体逻辑,这里简单地打印线程名称和计数,并通过 time.sleep(1) 方法让线程休眠 1 秒。
import threading
import time

# 自定义线程类
class MyThread(threading.Thread):
    def run(self):
        # 定义线程的逻辑
        for i in range(5):
            print("Thread:", self.getName(), "Count:", i)
            time.sleep(1)

# 创建线程对象
thread1 = MyThread()
thread2 = MyThread()

# 启动线程
thread1.start()
thread2.start()

# 等待线程执行完毕
thread1.join()
thread2.join()

print("Main thread finished")

Thread: Thread-5 Count: 0
Thread: Thread-6 Count: 0
Thread: Thread-5 Count: 1
Thread: Thread-6 Count: 1
Thread: Thread-5 Count: 2
Thread: Thread-6 Count: 2
Thread: Thread-5 Count: 3
Thread: Thread-6 Count: 3
Thread: Thread-5 Count: 4
Thread: Thread-6 Count: 4
Main thread finished
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-4 17:10:52 | 显示全部楼层
//www.bilibili.com/video/BV1QP4y1U7Yv/?spm_id_from=333.337.search-card.all.click&vd_source=bbd2966da727b3376515872084138922

协程——也叫微线程,核心 挂起 恢复,程序根据自己的需求进行调度(线程由CPU调度)。 异步编程:事件循环(event loop)决定执行哪个任务task,   corotine function 和普通函数差异,返回是 corotine  object 类似生成器。
await :
        在耗时操作执行期,暂停当前协程的执行,让事件循环去处理其他任务。一旦被 await 等待的异步操作完成,当前协程将继续执行下去。
        以及 等待一个已经提交到事件循环中的任务完成。
        只能等待可等待对象(awaitable objects)的完成。


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-5 07:08:29 | 显示全部楼层
async f1,f2——协程函数,运行返回 协程对象;  
协程函数单独调用: response = await f1(), await提交到 loop, // await可以接收一个任务返回值,没拿到就一直等。

coroutines=[f(),f2()]——携程对象 放置到 列表里,等待转成任务执行;

asyncio.run(asyncio.wait(coroutines))——执行任务 () //asyncio.run(main()), main协程中使用await asyncio.wait()来等待它们的完成。
done, pending = await asyncio.wait(coroutines)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-14 14:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表