定义模块。把python代码输入至文本文件中,然后以 “ .py ” 为后缀名进行保存,任何此类文件都会被自动认为是python模块。在模块顶层指定的所有变量名都会变成其属性(与模块对象结合的变量名),并且可以导出供客户端来使用。
模块的使用
客户端可以执行import或from语句,以使用我们刚才编写的简单模块文件。如果模块还没有加载,这两个语句就会去搜索、编译以及执行模块文件程序。
主要差别在于,import会读取整个模块,所以必须进行定义后才能读取它的变量名。 from将获取(或者说是复制)模块特定的变量名。
import使一个变量名引用整个模块对象,我们必须通过模块名称来得到该模块的属性。
from会把变量名复制到另一个作用域,所以它就可以让我们直接在脚本中使用复制后的变量名,而不需要通过模块
from语句,导入的变量名会复制到作用域内,在脚本中使用该变量名就可少输入一些:我们可以直接使用变量名,而无须再嵌套模块名称之后。
from*语句
当我们使用 * 时,会取得模块顶层所有附了值的变量名的拷贝。
import和from语句都会使用相同的导入操作。from * 形式只是多加个步骤,把模块中所有变量名复制到了进行导入的作用域之内。从根本上来说,这就是把一个模块的命名空间融入另一个模块中;同样地,实际效果就是可以让我们少输入一些。
模块会在第一次import或from时载入并执行,并且只在第一次如此。这是有意而为之的,因为该操作开销较大。在默认的情况下,python只对每个文件的每个进程做一次操作。之后的导入操作都只会取出以加载的模块对象。
import和from是赋值语句
就像def—样,import和from是可执行的语句,而不是编译期间的声明,而且它们可以 嵌套在if测试中,出现在函数def之中等,直到执行程序时,Python执行到这些语句, 才会进行解析。换句话来说,被导入的模块和变量名,直到它们所对应的import或仃om 语句执行后,才可以使用。此外,就像def—样import和from都是隐性的赋值语句。
• import将整个模块对象赋值给一个变量名。
• from将一个或多个变量名赋值给另一个模块中同名的对象。
模块命名空间
模块最好理解为变量名的封装,也就是定义想让系统其余部分看见变量名的场所。从技 术上来讲,模块通常相应于文件,而Python会建立模块对象,以包含模块文件内所赋值 的所有变量名。但是,简而言之,模块就是命名空间(变量名建立所在的场所),而存在于模块之内的变量名就是模块对象的属性。
文件生成命名空间
在模块文件顶层(也就是不在因数或类的主体内)毎一个赋值了的变量名都会变成该模块的属性。
例如,假设模块文件的顶层有一个像X = 1这样的赋值语句,而变量名X会变成M的属性,我们可在模块外以M.X的方式对它进行引用。变量名X对内其他程序而言也会 变成全局变量。
• 顶层的赋值语句会创建模块属性
• 模块的命名空间能通过属性__dict__或 dir(M)获取
• 模块是一个独立的作用域(本地变量就是全局变量)
属性名的点号运算
在Python之中,可以使用点号运算语法object .attribute获取任意的 object 的attribute 属性。
例如。表达式 module2.sys 会取出module2中赋值给sys的值。同样地,如果我们有内置的列表对象 L,而L.append会返回和该列表相关联的append方法对象。
当使用点号运算来读取变量名时,就把明确的对象提供给 Python,来从其中取出赋值的变量名。LEGB规则只适用于无点号运算的纯变量名。以下是其规则。
简单变量
X是指在当前作用域内搜索变量名X (遵循LEGB规则)。
点号运算
X.Y是指在当前范围内搜索X,然后搜索对象X之中的属性Y (而非在作用域内)。
多层点号运算
X.Y.Z指的是寻找对象XZ中的变最名Y,然后再找对象X.Y之中的Z。
通用性
点号运算可用于任何具有属性的对象:模块、类、C扩展类型等。