本节重点
- 包
- IO
- 序列化
- 可迭代对象与迭代器
- 生成器
- 多线程
一、包
定义:
通俗理解为带有多个模块的文件夹,只不过文件夹中有__ init __.py文件,包裹、管理模块。
1、导入包中的模块
# 类比导入模块时的方式
# 方式一
import package.first
import package.second
# 方式二
from package import first as one
from package import second
# 方式三
from package import * # 导入包中所有模块
'''
可通过__init__.py 中限定导入模块:__all__ = ["first","second"]
'''
2、直接导入包
import package
package.first.show()
'''
python2中需要在__init__.py中添加
from package import first
from package import second
python3貌似不用
'''
3、使用包模块中的代码:
package.first.show()
package.first.show_msg()
4、设置包模块的别名
import package.first as one
one.show()
two.show_msg()
二、IO
目的:小批量数据先在内存中处理,再进行持久化(硬盘、数据库等)
1、stringIO
from io import StringIO
str_io = io.StringIO() # 获取对象
# 写入数据
str_io.write("hello")
str_io.write("word")
# 获取内存中全部数据
content = str_io.getvalue()
print(content)
# 设定对象指针
str_io.seek(0)
result = str_io.read() # 默认全部读取,接受参数表示读取字节数
print(result)
'''
helloword
helloword
'''
2、BytesIO
from io import BytesIO
byte_io = io.BytesIO()
# 编码写入二进制数据
byte_io.write("syp".encode("utf-8"))
data = byte_io.getvalue()
print(data)
# 解码读取二进制数据
result = data.decode("utf-8")
print(result)
'''
b'syp'
syp
'''
三、序列化
定义
把内存数据保存到本地,可以做到数据持久化
1、pickle
通用序列化模块,可序列化任何数据
import pickle
# 序列化
mylist = [{"name":"syp","age":22},{"name":"dsy","age":22}]
file = open("mylist.serialize","wb") # 后缀
pickle.dump(mylist, file) # 打包序列化
file.close()
# 反序列化
file = open("mylist.serialize","rb")
my_list = pickle.load(file)
print(my_list)
file.close()
# 对类对象的序列化,本质上就是序列化其属性
class Student:
def __init__(self,name,age):
super().__init__()
self.name = name
self.age = age
stu = Student("syp",22)
file = open("stu.txt","wb")
pickle.dump(stu,file)
file.close()
file = open("stu.txt","rb")
my_list = pickle.load(file)
print(my_list.name,my_list.age)
file.close()
2、json
json序列化:只支持部分数据类型(列表、字典、int......),不支持自定义数据类型,比如自定义类,但是可以保存类的属性 json.dump(stu.__ dict __)。
import json
mylist = [{"name":"syp","age":22},{"name":"dsy","age":22}]
file = open("mylist.txt","w",encoding="utf-8")
json.dump(mylist,file)
file.close()
file = open("mylist.txt","r",encoding="utf-8")
mylist = json.load(file)
print(mylist)
'''
[{'name': 'syp', 'age': 22}, {'name': 'dsy', 'age': 22}]
'''
直接json序列化一个类对象会报错
class Student:
def __init__(self,name,age):
super().__init__()
self.name = name
self.age = age
stu = Student("syp",22)
file = open("mylist1.txt","w",encoding="utf-8")
json.dump(stu,file) # 报错
file.close()
'''
TypeError: Object of type Student is not JSON serializable
'''
但是可以只序列化其属性:
json.dump(stu.__dict__,file)
'''
{'name': 'syp', 'age': 22}
'''
四、可迭代对象
1、定义:
通俗理解为,for循环遍历取值的对象就是可迭代对象(列表、元组、字符串、集合、range),统一特征是具有__ iter __方法。
判断对象是否是可迭代对象
from collections import Iterable
result = isinstance([1,2,3],Iterable)
print(result)
# 判断对象是否为指定类型
result = isinstance([1,2,3],tuple)
print(result)
# 特征:可迭代对象都有__iter__方法
# 查看可迭代对象的所有方法
result = dir([1,2,3])
print(result)
'''
True
False
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
'''
2、迭代器
实现一个可迭代对象:
自定义一个类,并在类中重写iter和next方法,创建对象。
作用:
可以用数据位置获取下一个位置的值。
好处:
节省内存,不用每次将全部数据读入内存
class Myiterable(object):
def __init__(self):
super().__init__()
self.mylist = [1,2,3,4,5]
self.current_index = 0
# 重写方法
def __iter__(self):
return self
def __next__(self):
if self.current_index < len(self.mylist):
result = self.mylist[self.current_index]
self.current_index += 1
return result
else:
raise StopIteration # 抛出异常,停止迭代
myiter = Myiterable()
result = isinstance(myiter, Iterable)
print(result)
'''
True
'''
print(next(myiter))
print(next(myiter))
'''
1
2
'''
# 可用for循环打印出全部的数据
for value in myiter:
print(value)
'''
1
2
3
4
5
'''
3、生成器
定义:
特殊迭代器,for循环遍历,自动停止迭代。不会一开始保存所有数据,而是实时计算出结果。而迭代器在已经存好数据的容器中不断取值。
result = (x for x in range(4))
print(result,type(result))
value = next(result)
print(value)
value = next(result)
print(value)
value = next(result)
print(value)
'''
<generator object <genexpr> at 0x000001EE47771138> <class 'generator'>
0
1
2
'''
yield生成器:
出现yield关键字,暂停,返回结果。下次启动生成器在暂停位置继续,可返回多次值。
g = show_num()
result = next(g) # 第一次返回for循环中的第一个元素0
print(result)
result = next(g) # 第二次生成器继续for循环,返回下一个元素1
print(result)
result = next(g) # 返回2
print(result)
'''
0
1
2
'''
五、多线程
1、定义:
执行代码的分支,默认只有一个主线程,多个线程可同时执行。
2、应用场景:
百度网盘,多任务下载。
注意:python本质上没有多线程
3、示例:执行多线程
# 方法A与方法B为两个线程执行
import threading #使用threading模块
def methodA(count):
for i in range(count):
print("AA\n")
def methodB(count):
for i in range(count):
print("BB\n")
if __name__ == "__main__":
subthread1 = threading.Thread(target=methodA,args=(10,)) # 创建子线程
subthread2 = threading.Thread(target=methodB,kwargs={"count":5})
subthread1.start() # 执行子线程
subthread2.start()
'''
AA
AA
AABB
AA
AABB
AABB
AABB
AABB
AA
AA
'''
注意args接收的参数是元组形式,kwargs接收的是字典形式。
4、示例:线程守护
主线程结束时,子线程被直接销毁结束,运用到daemon参数。
import threading
import time
def methodA():
print("inAA",threading.current_thread())
print("这是在子线程中执行的")
while True:
print("AA")
time.sleep(0.2)
if __name__ == '__main__':
print("main",threading.current_thread())
sub = threading.Thread(target=methodA)
sub.setDaemon(True) # 设置守护线程,主线程退出会直接销毁子线程
sub.start()
time.sleep(1)
print("over")
'''
这是在子线程中执行的
AA
AA
AA
AA
AA
over
AA
AA
AA
(子线程的无限循环被终止)
'''
5、公共资源的争夺
如下两个线程都对g_num进行增加,但是不能达到预期的效果
import threading
g_num = 0
def sum1():
global g_num
for i in range(1000000):
g_num+=1
print("sum1",g_num)
def sum2():
global g_num
for i in range(1000000):
g_num+=1
print("sum2",g_num)
if __name__ == "__main__":
first = threading.Thread(target = sum1)
second = threading.Thread(target = sum2)
first.start()
second.start()
'''
sum2 1047819
sum1 1220658
'''
增加互斥锁来解决这个问题:
要对公共资源进行操作,必须先取得该资源上的锁,没有锁就不可以访问,当其他线程占用锁的时候不能抢夺,必须等其释放锁之后来获得锁。更详细的锁概念可以参考操作系统的相关书籍。
示例:互斥锁:
import threading
lock = threading.Lock() # 获得锁对象
g_num = 0
def sum1():
lock.acquire() # 获得锁
global g_num
for i in range(1000000):
g_num+=1
lock.release() # 释放锁
print("sum1",g_num)
def sum2():
lock.acquire() # 获得锁
global g_num
for i in range(1000000):
g_num+=1
lock.release() # 释放锁
print("sum2",g_num)
if __name__ == "__main__":
first = threading.Thread(target = sum1)
second = threading.Thread(target = sum2)
first.start()
second.start()
'''
sum1 1000000
sum2 2000000
'''
网友评论