python线程问题、深浅拷贝、属性动态设置、迭代器iter、生成器yield

一、发现之前没有线程的日志,写了一个简单的,参考来源:https://www.cnblogs.com/vamei/archive/2012/10/11/2720042.html

import threading
def demo(i):
    print("线程名",i)

try:
    i = 0
    # 开启线程数目
    tasks_number = 10
    print('测试启动')
    ths = []
    # threadLock = threading.Lock()
    while i < tasks_number:
        # target:运行目标内容, name:线程名 ,这里的args会作为target入参
        t = threading.Thread(target=demo,name=f"线程{i}",args=(i,))
        ths.append(t)
        i += 1
    for i in ths:
        i.start()
    for i in ths:
        i.join()
    print("退出线程")
except Exception as e:
    print(e)

 线程池

1、创建合理的线程数量,重用存在的线程,减少线程创建销毁带来的开销。
2、可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
3、提供定时执行、定期执行、单线程、并发数控制等功能。

import time
from concurrent.futures import ThreadPoolExecutor, wait, FIRST_COMPLETED, as_completed


def work(n):
    time.sleep(n)
    return n


if __name__ == '__main__':
    # max_workers表示最多工作的线程数
    executor = ThreadPoolExecutor(max_workers=10)
    # 提交线程需要执行的任务到线程池中,并返回该任务的句柄,注意submit()不是阻塞的,而是立即返回的
    t1 = executor.submit(work, 4)
    t2 = executor.submit(work, 1)
    t3 = executor.submit(work, 6)
    # 通过done()方法来判断线程是否完成, True表示已完成、False表示未完成
    print(f"t1 done: {t1.done()}")
    print(f"t2 done: {t2.done()}")
    print(f"t3 done: {t3.done()}")

    # 通过result()来获取线程返回的结果, timeout为获取结果的最长等待时间, 若为None则一直等待直到线程结束
    # print(f"t1 result: {t1.result(timeout=None)}")
    # print(f"t2 result: {t2.result(timeout=None)}")
    # print(f"t3 result: {t3.result(timeout=None)}")

    # fs:要执行的序列, timeout:等待的最大时间, return_when:wait返回结果的条件;
    # ALL_COMPLETED等待全部线程执行结束后返回,
    # FIRST_COMPLETED等待第一个线程结束时返回,
    # FIRST_EXCEPTION线程一旦产生异常事件就结束
    # wait的返回值包含了已完成done和未完成not_done的句柄
    # print(f"=== wait:{wait(fs=[t1,t2,t3], timeout=None, return_when=FIRST_COMPLETED)}")

    # 每完成一个线程响应一个结果,直到work_list中线程全部结束
    for future in as_completed([t1, t2, t3]):
        data = future.result()
        print(f"as_completed: {data}")

    # 使用map方法,无需提前使用submit方法;map输出顺序与列表的顺序相同
    for result in executor.map(work, [3, 2, 5], timeout=None):
        print(f"map: {result}")

二、深浅拷贝

浅拷贝只复制指向某个对象的指针而不复制对象本身,新旧对象还是共享同一块内存。

但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象

可变对象:列表、集合、字典(可以进行更改,并且更改后物理地址不会发生改变)
不可变对象:数字、字符串、元组(不可以进行更改,更改后就是一个新的对象了,物理地址发生了变化)

import copy
a=['hello',[1,2,3],{'a':1,'b':2},[[1],2]]
b=a
c=copy.copy(a)
print([id(x) for x in a])
print([id(x) for x in b])

a[0]='world'
a[1].append(4)
a[2]['a']=5

print('a=',a)
# a= ['world', [1, 2, 3, 4], {'a': 5, 'b': 2}, [[1], 2]]
print('b=',b)
# b= ['world', [1, 2, 3, 4], {'a': 5, 'b': 2}, [[1], 2]]
print('c=',c)
# c= ['hello', [1, 2, 3, 4], {'a': 5, 'b': 2}, [[1], 2]]
# 由于a[0]是不可变数据类型,所以a[0]修改了,c[0]仍然指向的是原来的地址

参考来源:https://zhuanlan.zhihu.com/p/25221086

三、属性动态设置

1、hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
2、getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
3、setattr(object, name, values)
给对象的属性赋值,若属性不存在,先创建再赋值。
4、delattr(object, name)
delattr函数用于删除name属性
delattr(x, ‘foobar’)相当于del x.foobar

四、迭代器和生成器 

python迭代器有两个基本的方法:iter() 生成迭代器next() 输出迭代器的下一个元素
生成器yield :调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行调用一个生成器函数,返回的是一个迭代器对象

l = [1, 2, 3, 4]
it = iter(l)  # 迭代器
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(next(it), "=====分割线=====")

def test():
    yield 1

print(type(test()))  # 只要使用了yield的函数,对象都是迭代器

def fibonacci(n):
    a, b, count = 0, 1, 0
    while True:
        if (count > n):
            return
        yield a  # 生成器yield,返回a
        a, b = b, a + b
        count += 1
        print("运行次数:", count)


f = fibonacci(10)  # f是一个迭代器,由生成器返回生成

print("迭代器返回值:", next(f))  # 运行到a结束,第一次不会打印count
print("--分割线--")
print("迭代器返回值:", next(f))  # 再调用一次,从上次运行位置开始。先打印count,再打印迭代器返回值

 

posted @ 2021-03-25 10:40  whitewall  阅读(92)  评论(0)    收藏  举报