python之8核心知识点

8.1 python工程组织结构之包、模块等的概念

  • 模块
    新建python file,生成带有.py后缀的文件称为模块

  • 包和目录差不多,唯一的区别在于包下面有一个_init_.py的文件

8.2 命名空间

  • 命名空间是变量到对象的映射集合。一般都是通过字典来实现的。主要可以分为三类:
    1、每个函数都有着自已的命名空间,叫做局部命名空间,它记录了函数的变量,包括函数的参
    数和局部定义的变量。
    2、每个模块拥有它自已的命名空间,叫做全局命名空间,它记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
    3、还有就是内置命名空间,任何模块均可访问它,它存放着内置的函数和异常。通俗点讲:命名空间就是为了确定全局唯一,当模块A中有变量c,模块B中也有一个变量c,此时,通过A.c来确定引用A中变量c.123

  • 命名空间的查找顺序
    当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:
    1、局部命名空间:特指当前函数或类的方法。如果函数定义了一个局部变量 x,或一个参数
    x,Python 将使用它,然后停止搜索。
    2、全局命名空间:特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python
    将使用它然后停止搜索。
    3、内置命名空间:对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或
    变量。
    4、如果 Python 在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 异常,如,
    NameError: name ‘xxx’ is not defined。

  • 当函数嵌套时的查找规则
    1、先在当前 (嵌套的或 lambda) 函数的命名空间中搜索
    2、然后是在父函数的命名空间中搜索
    3、接着是模块命名空间中搜索
    4、最后在内置命名空间中搜索

msg = "msg"
def my_func():
    name = " wiggin "
    def func_son():
         name = "xdclass " # 此处的name变量,覆盖了父函数的name变量
        print(name)
        # 调用内部函数
    func_son()
    print(name)
my_func()
  • 命名空间的生命周期
    1、内置命名空间在 Python 解释器启动时创建,会一直保留,不被删除。
    2、模块的全局命名空间在模块定义被读入时创建,通常模块命名空间也会一直保存到解释器退出。
    3、当函数被调用时创建一个局部命名空间,当函数返回结果 或 抛出异常时,被删除。每一个递归调用的函数都拥有自己的命名空间。
a = 1
def my_func(str):
    if a == 1:
        print(str)
       a = 24
my_func("file")

上面的程序会在报错,UnboundLocalError: local variable ‘a’ referenced before assignment
在python的函数中和全局同名的变量,如果你有修改变量的值就会变成局部变量,在修改之前对
该变量的引用自然就会出现没定义这样的错误了,如果确定要引用全局变量,并且要对它修改,
必须加上global关键字。

修改如下:

a = 1
def my_func(str):
    global a
    if a == 1:
        print(str)
        a = 24
my_func("file")
print(a)
  • 命名空间的访问
    1、局部命名空间的访问

    局部命名空间可以 locals() 来访问。
    locals 返回一个名字/值对的 dictionary。这个 dictionary 的键是字符串形式的变量名字,dictionary 的值是变量的实际值

def my_func():
  a = 1
  b = 2
  print(locals())
my_func()

输出:
{‘a’: 1, ‘b’: 2}

2、全局命名空间的访问
全局 (模块级别)命名空间可以通过 globals() 来访问。

a = 1
b = 2
print(globals())

输出:
{
name’: ‘main’,
doc’: None,
package’: None,
loader’: <_frozen_importlib_external.SourceFileLoader object at
0x00000255B062F548>,
spec’: None,
annotations’: {},
builtins’: <module ‘builtins’ (built-in)>,
file’: ‘C:/Users/wiggin/Desktop/xdclass/chapter12/class2.py’,
cached’: None,
‘a’: 1, ‘b’: 2
}

3、locals 与 globals 之间的区别
locals 是只读的,但globals是可读写的

def my_func():
    x = 123
    print(locals())
    locals()["x"] = 456
    print("x=", x)
y = 123
my_func()
globals()["y"] = 111
print("y=", y)

输出:
x=123
y=111

8.3 导入模块
import module_name

import class2
print(class2.a)

import module_name as alias

# 导入模块并重命名为xd
import xdclass_python_chapter12_class3 as xd
print(xd.name)

import导入时,

  1. 查找一个模块,如果有必要还会加载并初始化模块。
  2. 在局部命名空间中为 import 语句发生位置所处的作用域定义一个或多个名称。

当一个模块首次被导入时,Python 会搜索该模块,如果找到就创建一个 module 对象并初始化它。 如果指定名称的模块未找到,则会引发 ModuleNotFoundError。 当发起调用导入机制时,Python 会实现多种策略来搜索指定名称的模块。
特别注意:当模块首次被导入时,会执行模块里面的代码

使用importlib模块进行模块的导入,基本语法如下
import importlib
importlib.import_module(“module_name”)

import importlib
module = importlib.import_module("xdclass_python_chapter12_class3")

如果想导入另一个包中的模块,可以使用如下语法:
from package import module

如果想导入多层包中的模块,可以使用如下语法:
from package.son import module

8.4 导入变量
from module import variable

from class2 import a
print(a)

别注意:当模块首次被导入时,会执行模块里面的代码
如class2中的内容为:

a = 1111
print("hello world")

运行结果会先输出hello world,在打印a值

如果要导入多个变量,可用逗号隔开
如果要导入大量变量,可使用*号导入

from class2 import a, b
from class2 import *

8.5 导包机制
python 导入机制:
导入期间,会在 sys.modules 查找模块名称,如存在则其关联的值就是需要导入的模块,导入过程完成。 然而,如果值为 None ,则会引发ModuleNotFoundError。 如果找不到指定模块名称,Python 将继续搜索该模块。
如果指定名称的模块在 sys.modules找不到,则将发起调用 Python 的导入协议以查找和加载该模块。 此协议由两个概念性模块构成,即 查找器和 加载器。查找器的任务是确定是否能使用其所知的策略找到该名称的模块。 同时实现这两种接口的对象称为 导入器—— 它们在确定能加载所需的模块时会返回其自身。

例如
from class5_import import a

  • 在sys.modules中查找符号"class5_import"
  • 如果符号存在,则获得符号class5_import对应的module对象
    从的dict中获得符号"a"对应的对象,如果"a"不存在,则抛出异常
  • 如果符号class5_import不存在,则创建一个新的module对象,注意,这时,module对象的dict为空
  • 执行class5_import.py中的表达式,填充的dict
  • 从的dict中获得"a"对应的对象,如果"a"不存在,则抛出异常

模块 class5.py

from class2 import a
b = 11
print(a)

模块 class5_import.py

from class5 import b
a = 1

执行过程如下:
1、执行class5.py中的from class5_import import a,由于是执行的python class5.py,所以在sys.modules中并没有存在,首先为B.py创建一个module对象(),注意,这时创建的这个module对象是空的,里边啥也没有,在Python内部创建了这个module对象之后,就会解析执行class5_import.py,其目的是填充这个dict。
2、执行class5_import.py中的 from class5 import b,在执行class5_import.py的过程中,会碰到这一句,首先检查sys.modules这个module缓存中是否已经存在了,由于这时缓存还没有缓存,所以类似的,Python内部会为class5.py创建一个module对象(),然后,同样地,执行class5.py中的语句
3、再次执行class5.py中的from class5_import import a,这时,由于在第1步时,创建的对象已经缓存在了sys.modules中,所以直接就得到了,但是,注意,从整个过程来看,我们知道,这时还是一个空的对象,里面啥也没有,所以从这个module中获得符号"a"的操作就会抛出异常。如果这里只是import class5_import,由于"class5_import"这个符号在sys.modules中已经存在,所以是不会抛出异常的。

8.6 说说_init_.py的作用及用法
说说_init_.py的作用:

  • 标志所在目录是一个模块包
  • 本身也是一个模块
  • 可用于定义模糊导入时要导入的内容

我们使用from package import * 会报错误,如果想使用该语法不报错,可以在__init__.py中定义要导入的模块
我们可以在__init__.py文件中,使用__all__ = [‘module_name1’,‘module_name2’]定义号匹配时要导入的模块,之后再导入的时候,就可以使用通配符进行模糊导入

  • 导入一个包的时候,包下的__init__.py中的代码会自动执行
  • 用于批量导入模块

当我们的许多模块中,都需要导入某些公共的模块,此时,可以在__init__.py中进行导入,之后直接导入该包即可

8.7 _all_和_name_的作用及用法
__all__的作用及其用法:
__all__是list的结构

  • 在普通模块中使用时,表示一个模块中允许哪些属性可以被导入到别的模块中
  • 在包下的__init__.py中,可用于标识模糊导入时的模块

__name__的作用及其用法:

  • __name__这个系统变量显示了当前模块执行过程中的名称,如果当前程序运行在这个模块中,name 的名称就是__main__如果不是,则为这个模块的名称。
  • __main__一般作为函数的入口,类似于C语言,尤其在大型工程中,常常有if name == “main”:来表明整个工程开始运行的入口。
def my_fun():
	if __name__ == "__main__":
	print("this is main")
my_fun()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uncle_Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值