在笔者推出的Python基础与拾遗9讲中,与大家分享了Python中基础的语法与注意事项,尤其讲述了Python语言与其他语言在使用上的区别。在阅读完毕Python基础与拾遗过后,应该就可以编写一些基础的Python程序,并且能够使用一些Python中独有的技巧了。但是Python语言是一门面向对象设计的语言,在几乎所有的大型Python工程中,均通过面向对象技术进行搭建。因此,Python进阶与拾遗部分就应运而生了,主要与大家分享Python中模块与面向对象程序设计的一些基础技巧,从最基本的Python模块开始,下面开始干货。
import # 以一个整体获取一个模块
from # 允许客户端从一个模块文件中获取特定的变量名
m.reload # 不终止Python程序的情况下,重新载入m模块文件
模块和类是重要的命名空间,在一个模块文件的顶层定义的所有变量名都成了被导入的模块对象属性,在导入时,模块全局作用域变成了模块对象的命名空间。
使用模块的好处有:
程序在第一次导入指定文件时,会执行三个步骤:
import module_a # 正确
import dir1/dir2/module_a # 错误
import sys
sys.path # 打印模块的搜索路径
sys.path,支持打印。包含以下四类,顺序如下:
如果要修改模块的搜索路径,可以直接修改sys.path列表,比如常见在sys.path中添加项:
import sys
sys.path.append('module_path') # 添加模块的搜索路径
在import b时可能会加载:
import使一个变量名引用整个模块对象,必须通过模块名称得到该模块的属性。
import numpy as np
np.pi # 3.141592653589793
from random import shuffle
shuffle(list) # 打乱列表
from A import f
from B import f # B中的f覆盖掉了A中的f
from random import *
shuffle(list) # 打乱列表
randint(a, b) # 产生[a, b]范围内的随机整数
注意,在Python 2.6及之后的版本中,from … import *可以用在一个函数内。但是在Python 3.0及之后的版本中,from … import *只能出现在一个模块文件的顶部。
递归式的from导入可能会出错。
# recur1.py
X = 1
import recur2
Y = 2
# recur2.py
from recur1 import X
from recur1 import Y # 报错 ImportError: cannot import name 'Y' from partially initialized module 'recur1' (most likely due to a circular import)
常用as语句,让模块可以在脚本中给予不同的变量名。
import numpy as np
from random import shuffle as sf
np.pi # 3.141592653589793
l = [1, 2, 3, 4, 5]
sf(l)
l # [5, 4, 2, 3, 1]
# mod_0.py
a = 1
b = [2, 3, 4]
在第一个进程中:
import mod_0
mod_0.a # 1
mod_0.b # [2, 3, 4]
mod_0.a = 100
mod_0.b[0] = 200
import mod_0
mod_0.a # 100
mod_0.b # [200, 3, 4]
from mod_0 import a, b
a # 100
b # [200, 3, 4]
在第二个进程中:
import mod_0
mod_0.a # 1
mod_0.b # [2, 3, 4]
from __future__ import featurename
__name__属性。如果文件是以顶层程序文件执行,在启动时,__name__就会被设置为字符串"__main__"。如果文件被导入,__name__就会被设成客户端所了解的模块名。
用名称字符串导入模块,可以用exec函数或者__import__函数。
mod_name = "string"
exec("import " + mod_name)
string
<module 'string' from 'D:\\Anaconda3\\lib\\string.py'>
mod_name = "string"
string = __import__(mod_name)
string
<module 'string' from 'D:\\Anaconda3\\lib\\string.py'>
# mod_0.py
a = 1
b = [2, 3, 4]
def f():
pass
在一个进程中:
import mod_0
list(mod_0.__dict__.keys())
"""
输出:
['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'a', 'b', 'f']
"""
dir(mod_0)
"""
输出:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'f']
"""
模块程序代码绝对无法看到其他模块内的变量名,除非明确地进行了导入,全局变量亦如此。
比如,在工程目录下,有一个mod_0.py,里面内容是:
# mod_0.py
X = 88
def f():
global X
X = 99
在工程的main执行函数中:
import mod_0
def main():
X = 11
mod_0.f()
print(X, mod_0.X) # 11 99
if __name__ == "__main__":
main()
在被导入的模块中导入其他模块时,会创建命名空间的嵌套。
比如,在工程目录下,有一个mod_1.py,里面内容是:
# mod_3.py
X = 3
一个mod_2.py,里面内容是:
# mod_2.py
import mod_3
X = 2
一个mod_1.py,里面内容是:
# mod_1.py
import mod_2
X = 1
在工程的main执行函数中:
import mod_1
def main():
print(mod_1.X, mod_1.mod_2.X, mod_1.mod_2.mod_3.X) # 1 2 3
if __name__ == "__main__":
main()
# mod_0.py
a = 1
b = [2, 3, 4]
_c = {
'a':5, 'b':6}
在工程执行main函数中:
from mod_0 import *
def main():
print(a) # 1
print(b) # [2, 3, 4]
# print(_c) # 报错 NameError: name '_c' is not defined
if __name__ == "__main__":
main()
# mod_0.py
__all__ = ["a", "b"]
a = 1
b = [2, 3, 4]
c = {
'a':5, 'b':6}
d = (7, 8, 9)
在工程执行main函数中:
from mod_0 import *
def main():
print(a) # 1
print(b) # [2, 3, 4]
# print(c) # 报错 NameError: name 'c' is not defined
# print(d) # 报错 NameError: name 'd' is not defined
if __name__ == "__main__":
main()
reload函数会强制已加载的模块代码重新载入并执行,传递给reload的是已经存在的模块对象。在Python 2.6及之后的版本中,reload是内置函数。在Python 3.0及之后的版本中,reload函数已经被移入imp标准库模块,在使用时需要导入。
# mod_0.py
a = 1
b = [2, 3, 4]
在一个进程中:
import mod_0
mod_0.a # 1
mod_0.b # [2, 3, 4]
mod_0.a = 100
mod_0.b[0] = 200
mod_0.a # 100
mod_0.b # [200, 3, 4]
from importlib import reload
reload(mod_0)
mod_0.a # 1
mod_0.b # [2, 3, 4]
在另一个进程中:
from mod_0 import a, b
a # 1
b # [2, 3, 4]
a = 100
b[0] = 200
a # 100
b # [200, 3, 4]
from importlib import reload
reload(mod_0)
a # 100
b # [200, 3, 4]
以上,欢迎各位读者朋友提出意见或建议。
欢迎阅读笔者后续博客,各位读者朋友的支持与鼓励是我最大的动力!
written by jiong
万缕千丝终不改,任他随聚随分。
韶华休笑本无根。
好风凭借力,送我上青云。