一:importlib模块
1,动态导入模块,即根据字符串形式的路径导入模块
import importlib
path = "settings.Foo"
m,c= path.rsplit(".",1)
module = importlib.import_module(m)
cls = getattr(module,c)
for key in dir(cls):
if key.isupper():
print(key,getattr(cls,key))
2,模块引入检查,即检查并观察一个模块是否可以引入
import importlib.util
import importlib
def check_module(module_name):
module_spec = importlib.util.find_spec(module_name)
if module_spec is None:
print("Module :{} not found".format(module_name))
return None
else:
print("Module:{} can be imported!".format(module_name))
return module_spec
def import_module_from_spec(module_spec):
module = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
return module
if __name__ == "__main__":
module_spec = check_module("collections")
if (module_spec):
module = import_module_from_spec(module_spec)
print(dir(module))
二:上下文管理器
上下文管理器规定了某个对象的使用范围,当进入或者离开了使用范围,都会有相应的一些调用,比如代码块开始时执行一些准备,代码块结束时结束一些操作。它更多的是用于资源的分配和释放上,即在开始时分配资源,结束时释放一些资源。比如在执行数据库查询时要建立连接,查询结束后要释放连接;写文件时要先打开文件,写结束后,要关闭文件等等。还有,就是资源的加锁和解锁,比如在使用多线程时,可能会用到加锁和解锁。
对于上下文管理器的使用,最常见的是使用with语句,with语句可构建资源的分配与释放的语法糖。
要实现一个自定义的上下文管理器,肯定要实现两个方法,一是进入对象范围时的准备工作,二是离开对象范围时的结束工作。
Python提供了两个类的方法分别实现上述功能:
__enter__进入对象范围时(一般代码块开始)被调用;
__exit__离开对象范围时(代码块结束)被调用;
因此,一个Python类,只要实现了上述两种方法,就可以说是一个上下文管理器。
三:深拷贝与浅拷贝
为了让一个对象发生改变时不对原对象产生副作用,此时,需要一份这个对象的拷贝,python 提供了 copy 机制来完成这样的任务,对应的模块是 copy。在 copy 模块中,有 copy 函数可以完成浅拷贝,有 deepcopy 函数可以完成深拷贝。
在 python 中,标识一个对象唯一身份的是:对象的id(内存地址),对象类型,对象值,而浅拷贝就是创建一个具有相同类型,相同值但不同id的新对象。
对可变对象而言,对象的值一样可能包含有对其他对象的引用,浅拷贝产生的新对象,虽然具有完全不同的id,但是其值若包含可变对象,这些对象和原始对象中的值包含同样的引用。
可见浅拷贝产生的新对象中可变对象的值在发生改变时会对原对象的值产生副作用,因为这些值是同一个引用。
浅拷贝仅仅对对象自身创建了一份拷贝,而没有在进一步处理对象中包含的值。因此使用浅拷贝的典型使用场景是:对象自身发生改变的同时需要保持对象中的值完全相同,比如 list 排序。
深拷贝不仅仅拷贝了原始对象自身,也对其包含的值进行拷贝,它会递归的查找对象中包含的其他对象的引用,来完成更深层次拷贝。因此,深拷贝产生的副本可以随意修改而不需要担心会引起原始值的改变。
对不可变类型,如字符串,深拷贝与浅拷贝得到的id值与原值一样,即引用的是同一个值;
对可变类型,如列表,深拷贝与浅拷贝得到的id值均与原值不一样。
import copy
a = [[1,2,3],4,5,6,7]
b = copy.copy(a)
print(id(a),id(b)) # 2413605880456 2413605881736
b[0][0]=0
print(a,b) # [[0, 2, 3], 4, 5, 6, 7] [[0, 2, 3], 4, 5, 6, 7]
c = copy.deepcopy(a)
c[0][0]=9
print(a,c) # [[0, 2, 3], 4, 5, 6, 7] [[9, 2, 3], 4, 5, 6, 7]
自定义拷贝机制:
使用 _copy_ 和 __deepcopy__ 可以完成对一个对象拷贝的定制。