python基本使用(2)

本文详细介绍了Python的基础数据结构如元组、列表、字典等,并深入探讨了多线程编程的应用技巧,包括线程的创建、join功能、queue使用、GIL的影响以及Lock锁的正确使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. 元组tuple  

2. 列表list

3. 多维列表

4. 字典 dictionary

5. import 模块

6. 循环中的 continue、break

7. 错误处理try

8. zip、map、lambda功能

9. copy & deepcopy 浅复制&深复制

10. 多线程


小前提:元组tuple和列表list都是一种有序列表,二者又有所区别。

主要参考:百家号

  • 申明与赋值:元组使用小括号,列表使用方括号,元素之间也是用英文逗号分隔,当元组只有一个元素时,需要在元素的后面加一个英文逗号分隔符,以防止与表达式中的小括号混淆;
  • 元组是不可修改类型,不能对元组的元素进行插入和删除运算,只能通过再构造一个新的元组替换旧的元组来实现。

1. 元组tuple  

a_tuple=(1,6,7,12)   #元组的定义可以用()或什么都不加
b_tuple=3,4,5,7

a_list=[12,2,4,5,9]   #列表的定义用[]
for a in b_tuple:
    print(a)

for index in range(len(a_list)):
    print('index=',index,'number in list=',a_list[index])

结果为

>>> 
 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/3.py 
3
4
5
7
index= 0 number in list= 12
index= 1 number in list= 2
index= 2 number in list= 4
index= 3 number in list= 5
index= 4 number in list= 9

2. 列表list

a=[3,6,7,2,10,7]
b=[1,2]
c=[2,4,6]
d=[1,3,4,5,6,7,8]

#添加
a.append(9)
#print(a)
print('a appended is:',a)

b.insert(2,8) #insert函数,第一个参数表示列表的位置,第二个参数表示具体加的数字
print("b inserted is:",b)

#移除
c.remove(2)     #表示去掉原列表中首次出现的2
print('c removed is:',c)

#特定打印
print(d[2])     #打印列表中第二位
print(d[-1])    #打印列表中最后一位,用-1表示  -i表示倒数第i位
print(d[0:3])   #打印列表中前三位(即0、1、2位),用:,等价于print(a[:3])
print(d[3:])    #打印列表中第三位及以后

#索引
print(a.index(2))   #第一次出现2的位数,index后面的值是列表中的数值

#查看某个数字出现的次数
print(a.count(7))   #计算列表中出现7的次数

#排序
a.sort()           #sort后不加参数,默认从小到大排序
print('small to big is:',a) 

a.sort(reverse=True)      #sort加参数,从大到小排序
print('big to small is:',a)

结果为

>>> 
 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/3.py 
a appended is: [3, 6, 7, 2, 10, 7, 9]
b inserted is: [1, 2, 8]
c removed is: [4, 6]
4
8
[1, 3, 4]
[5, 6, 7, 8]
3
2
small to big is: [2, 3, 6, 7, 7, 9, 10]
big to small is: [10, 9, 7, 7, 6, 3, 2]

3. 多维列表

用到模块 numpy、pandas

a=[1,2,3]           #一维list
muti_a=[[1,2,3],[2,5,4],[6,4,5]]      #多维list

print(a[1])
print(muti_a[0][2])        #多维下的第0行,第2列

结果为

>>> 
 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
2
3

4. 字典 dictionary

 与 list 类似,dictionary功能更多,但是存档形式无需顺序

a_list=[1,2,3]           #一维 dictionary
b_dic={'apple':1,'orange':[1,2],'pear':3}       #key与内容value对应,内容可以是字典嵌套
c_dic={1:'monday','no':'saturday'}       #与上面形式不同,但是仍然是key与内容对应的形式

print(a_list[1])
print(b_dic['apple'])        #多维下的第0行,第2列

#删除元素
del b_dic['pear']
print(b_dic)

#增加元素
c_dic['sunday']=3
print(c_dic)              #增加后打印出的不一定按顺序

结果为

 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
2
1
{'apple': 1, 'orange': [1, 2]}
{1: 'monday', 'no': 'saturday', 'sunday': 3}

5. import 模块

5.1 import+模块,模块可以是 python 自带或者自己安装的,

import time  #加载模块的第一种方法
#import time as t  #模块简称为t
#from time import time,localtime  #加载time中的指定模块
#from time import *  #加载time中所有功能,也可以直接调用localtime()

print(time.localtime())
#print(time.time())
#print(localtime()) 第三种,前面就不用加time了

结果

 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
time.struct_time(tm_year=2018, tm_mon=3, tm_mday=17, tm_hour=9, tm_min=21, tm_sec=44, tm_wday=5, tm_yday=76, tm_isdst=0)

5.2 import自己创建的模块

自己的模块可以在python默认的外部模块地址下,也可以在和调用它的模块在同一目录下

6. 循环中的 continue、break

a=True
while a:
    b=input('type something')
    if b=='1':
        #a=False
        break    #终止
        #continue #直接跳过后面的,重复上面的
    else:
        pass    #表示什么也不做
print('finish run')

结果

>>> 
 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
type something2
type something3
type something1
finish run

7. 错误处理try

try:
    file=open('abc','r+w')
except Exception as e:      #将报错存储在e中
    print(e)
    print("there is no file name as abc")
    response = input('do you want to create a new file as abc?')
    if response=='y':
        file=open('abc','w')
    else:
        pass
else:   #与try对应
    file.write('string:abc') #写入的内容
    file.close()

输出结果为

 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
[Errno 2] No such file or directory: 'abc'
there is no file name as abc
do you want to create a new file as abc?y

8. zip、map、lambda功能

zip:zip函数接收任意多个序列作为参数,合并后返回一个 tuple 列表,zip(a,a,b)也可以

>>> a=[1,2,3]
>>> b=[4,5,6]
>>> zip(a,b)
<zip object at 0x0000000002E5AEC8>    #返回的是一个功能
>>> list(zip(a,b))     #要想可视化,变成list
[(1, 4), (2, 5), (3, 6)]
>>> for i,j in zip(a,b):
	print(i/2,j*2)

	
0.5 8
1.0 10
1.5 12

lambda:定义简单函数,实现简化代码的功能

>>> def fun1(x,y)
SyntaxError: invalid syntax
>>> def fun1(x,y):
	return x+y

>>> fun1(3,4)
7
>>> fun2=lambda x,y:x-y   #冒号前的x,y为自变量,冒号后x+y为具体运算
>>> fun2(9,3)
6

map:把函数和参数绑定在一起

>>> list(map(fun1,[2,4],[1,6]))
[3, 10]
>>> list(map(fun1,[2,4,7],[1,6]))  #参数形式必须一样,否则最后一个数字不识别
[3, 10]
>>> list(map(fun1,[2,4,7],[1,6,4]))
[3, 10, 11]

9. copy & deepcopy 浅复制&深复制

copy也是 python 中的一个模块 

>>> import copy
>>> a=[2,4,5]
>>> b=a      #第一种:完全copy,在内存中处于同一位置
>>> id(a)
48606984
>>> id(b)
48606984
>>> b[0]=9    #改变b的值,a的值也会相应变化
>>> a
[9, 4, 5]
>>> print(id(a)==id(b))
True
>>> c=copy.copy(a)     #第二种:浅copy,只copy最外围的对象本身,
>>> print(id(a)==id(c))  #id不同
False
>>> c[1]=22
>>> a
[9, 4, 5]
>>> c
[9, 22, 5]
>>> a=[1,2,[3,4]]    #处于第二层的[3,4]的id不会被copy,所以也没有变化
>>> d=copy.copy(a)
>>> id(a)==id(d)
False
>>> id(a[2])==id(d[2])      #第二层(外围)id一样
True
>>> a[0]=11
>>> d
[1, 2, [3, 4]]
>>> a[2][0]=33
>>> d
[1, 2, [33, 4]]
>>> e=copy.deepcopy(a)        #第三种copy,对外围和内部都进行了copy,id不同
>>> e
[11, 2, [33, 4]]
>>> id(e[2])==id(a[2])
False
>>> id(e)==id(a)
False

10. 多线程

参考https://morvanzhou.github.io/tutorials/python-basic/threading/

10.1 添加线程

import threading

def thread_job():
    print('this is an added Thread,number is %s'% threading.current_thread())   # % 前不能加,
def main():
    added_thread=threading.Thread(target=thread_job) #添加的线程,大写“T”,实现的功能是thread_job

    print(threading.active_count())     #获取已激活的线程数
    print(threading.enumerate())        #查看所有线程信息
    print(threading.current_thread())   #查看现在正在运行的线程

    added_thread.start() #运行添加的线程

if __name__=='__main__':    # :不能丢
    main()

结果

 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
2
[<_MainThread(MainThread, started 8320)>, <Thread(SockThread, started daemon 4324)>]
<_MainThread(MainThread, started 8320)>
this is an added Thread,number is <Thread(Thread-1, started 8604)>
>>> 

多线程与单线程执行耗时比较:https://www.cnblogs.com/rrxc/p/4103367.html

import threading
from time import sleep
import time

def task1():
    print("Task 1 executed")
    sleep(1)
def task2():
    print("Task 2 executed")
    sleep(5)

print("多线程:")
time_start = time.time()
threads = []  #创建一个线程列表,用于存放需要执行的子线程
t1 = threading.Thread(target=task1) #创建第一个子线程,子线程的任务是调用task1函数,注意函数名后不能有()
threads.append(t1) #将这个子线程添加到线程列表中
t2 = threading.Thread(target=task2) #创建第二个子线程
threads.append(t2)

for t in threads: #遍历线程列表
    t.setDaemon(True)  #将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起
    t.start() #启动子线程
time_end = time.time()
total_time = time_end - time_start
print("多线程下耗时:",format(total_time))
print(threading.active_count())     #获取已激活的线程数
print(threading.enumerate())        #查看所有线程信息
print(threading.current_thread())   #查看现在正在运行的线程

#单线程
print("单线程:")
start_time = time.time()
task1()
task2()
end_time = time.time()
totaltime = end_time - start_time
print("单线程下耗时:",format(totaltime))

'''
D:\应用软件\python\python.exe F:/BaiduNetdiskDownload/04-深度学习课程/TensorFlow教程/Tensorflow视频教程/tensorflowTUT源码/RNN.py
多线程:
Task 1 executed
Task 2 executed
多线程下耗时: 0.0009999275207519531
3
[<Thread(Thread-2, started daemon 14720)>, <Thread(Thread-1, started daemon 12460)>, <_MainThread(MainThread, started 15332)>]
<_MainThread(MainThread, started 15332)>
单线程:
Task 1 executed
Task 2 executed
单线程下耗时: 6.0

Process finished with exit code 0

'''

结果显示:多线程耗时远远小于单线程。

10.2  join功能

join:在启动线程后调用 join,可以使输出顺序按我们想要的来。

import threading
import time

def thread_job():
    print('T1 start\n')
    for i in range(10):
        time.sleep(0.1)
    print('T1 finish\n')
def main():
    added_thread=threading.Thread(target=thread_job,name='T1') #添加的线程,大写“T”,实现的功能是thread_job

    added_thread.start() #开始添加的线程
    added_thread.join()  #若不加join,则不会按我们想要的顺序执行
    print('all done\n')

if __name__=='__main__':    # :不能丢
    main()

加了 join 的运行结果

>>> T1 finish


 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
T1 start
T1 finish

all done

不加 join 的运行结果

>>> T1 finish


 RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/4.py 
T1 start
all done


>>> T1 finish

10.3 queue功能

线程没有返回值,需要放在队列中

import threading
import time
from queue import Queue      #队列的标准模块

def job(l,q):
    for i in range(len(l)):
        l[i]=l[i]**2
    q.put(l)

def multithreading():
    q=Queue()               #多线程函数中的Queue用来保存返回值
    threads=[]
    data=[[1,2,3],[3,4,3],[4,5,5],[5,6,7]]
    for i in range(4):     #定义四个线程
        t=threading.Thread(target=job,args=(data[i],q))  
        t.start()
        threads.append(t)  #把每个线程append到线程列表中
    for thread in threads:
        thread.join()
    results=[]
    for _ in range(4):
        results.append(q.get())   #q.get()表示按顺序从q中拿出一个值
    print(results)

if __name__=='__main__':    # :不能丢
    multithreading()

'''
[[1, 4, 9], [9, 16, 9], [16, 25, 25], [25, 36, 49]]
'''

10.4 GIL不一定有效率

python的多线程不是同时进行,是通过线程之间不停的切换实现的,且一次性只能处理一个东西,即GIL,所以不一定达到大量缩短时间的效果。

GIL:http://cenalulu.github.io/python/gil-in-python/

import threading
from queue import Queue
import copy
import time

def job(l, q):
    res = sum(l)
    q.put(res)

def multithreading(l):
    q = Queue()
    threads = []
    for i in range(4):
        t = threading.Thread(target=job, args=(copy.copy(l), q), name='T%i' % i)
        t.start()
        threads.append(t)
    [t.join() for t in threads]
    total = 0
    for _ in range(4):
        total += q.get()
    print(total)

def normal(l):
    total = sum(l)
    print(total)

if __name__ == '__main__':
    l = list(range(1000000))
    s_t = time.time()
    normal(l*4)
    print('normal: ',time.time()-s_t)
    s_t = time.time()
    multithreading(l)
    print('multithreading: ', time.time()-s_t)

结果为

 RESTART: C:\Users\Administrator\AppData\Local\Programs\Python\Python36\4.py 
1999998000000
normal:  0.17600011825561523
1999998000000
multithreading:  0.13700008392333984

按理来说,预计线程下会快3-4倍,但实际上并没有,就是因为 GIL 的原因。

10.5 Lock锁

lock 在不同线程使用同一内存时,能确保线程之间互不影响,使用lock的方法是, 在每个线程执行运算修改共享内存之前,执行lock.acquire()将共享内存上锁, 确保当前线程执行时,内存不会被其他线程访问,执行运算完毕后,使用lock.release()将锁打开, 保证其他的线程可以使用该共享内存。

import threading

def job1():
    global A,lock
    #lock.acquire()
    for i in range(10):
        A+=1
        print('job1',A)
    #lock.release()

def job2():
    global A,lock
    #lock.acquire()
    for i in range(10):
        A+=10
        print('job2',A)
    #lock.release()

if __name__=='__main__':
    #lock=threading.Lock()
    A=0
    t1=threading.Thread(target=job1)
    t2=threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

结果为(注意:此结果并不一定每次一样,也可能是完好的结果,结果并不固定)

job1job2 11
job2 21
job2 31
job2 41
job2 51
job2 61
job2 71
job2 81
job2 91
job2 101
 1
job1 102
job1 103
job1 104
job1 105
job1 106
job1 107
job1 108
job1 109
job1 110

出现乱码,加 lock 后代码为

import threading

def job1():
    global A,lock
    lock.acquire() #上锁
    for i in range(10):
        A+=1
        print('job1',A)
    lock.release() #将锁打开

def job2():
    global A,lock
    lock.acquire()
    for i in range(10):
        A+=10
        print('job2',A)
    lock.release()

if __name__=='__main__':
    lock=threading.Lock()
    A=0
    t1=threading.Thread(target=job1)
    t2=threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

此时结果为

 RESTART: C:\Users\Administrator\AppData\Local\Programs\Python\Python36\4.py 
job1 1
job1 2
job1 3
job1 4
job1 5
job1 6
job1 7
job1 8
job1 9
job1 10
job2 20
job2 30
job2 40
job2 50
job2 60
job2 70
job2 80
job2 90
job2 100
job2 110

问(来自莫凡视频下的评论):这里把

t1=threading.Thread(target=job1)
t2=threading.Thread(target=job2)

改成

t1=threading.Thread(target=job1())
t2=threading.Thread(target=job2())

同样能达到 lock 的效果???

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值