疫情环境下的网络学习笔记 python 3.27-3.28

3.27

昨日回顾

  1. 算法:高效解决问题的方法

    二分法+递归

  2. 在递归多层函数时,要考虑每一层返回的值

  3. 面向过程编程:一步步解决问题,优点:复杂问题简单化,缺点:扩展性差

  4. 匿名函数:lambda,临时使用的函数

    lambda x,y:x+y
    
  5. 模块:一堆功能的集合体

    内置,第三方:拿来就用

    自定义:不同文件中共用的功能放进模块,减少代码冗余

  6. 导入模块发生的三件事

    1. 执行代码
    2. 产生名称空间
  7. 引用:模块名.功能名

今日内容

  1. 一个python文件有几种用途
  2. 执行python文件与导入python文件的区别
  3. import发生的事情
  4. from import
  5. 循环导入问题
  6. 苏索模块的路径与优先级
  7. 区分python文件的两种用途
  8. 编写一个规范的模块
  9. 包(重要)
  10. 软件开发的目录规范

正课

python文件的几种用途

  1. 被当作程序直接运行
  2. 当作模块被导入

导入模块时执行的三个步骤:

  1. 造一个模块的名称空间
  2. 开始执行模块的代码,运行中产生的名字放在名称空间内
  3. 在当前位置造一个名字:模块名,指向刚刚创建的名称空间

二者的区别:

导入的模块的名称空间在主程序运行完才会销毁

区分文件的用途__name__

  1. 当foo.py被运行时,__name__的值为__main__
  2. 当foo.py 被当作模块被导入时,__name__的值为foo

__name__可以在不同应用场景下对文件执行不同的操作

if __name__ == '__main__':
    foo.py被当做脚本执行时运行的代码
else:
    foo.py被当做模块导入时运行的代码

from...import

普通地使用import...as...,每次使用模块的功能都需要 模块名.功能名

  • 优点:指名道姓地操作模块名称空间中的名字,不会与当前名称空间中的名字冲突
  • 缺点:加前缀麻烦

为了简洁,可以使用 from 模块名 import 功能名,直接使用模块中的功能名

from foo import x
from foo import get
from foo import change

print(x)
print(get)

使用from foo import..的三个步骤

  1. 产生一个模块的名称空间
  2. 运行foo.py,将运行过程中产生的名字都丢到模块的名称空间去
  3. 在当前名称空间拿到一个名字,该名字与模块名称空间中这个名字的内存地址绑定

from import优缺点

  • 优点:不用加前缀,代码更精简
  • 缺点:容易与当前名称空间混淆

一行可以用逗号分隔,导入多个名字

from foo import x,get,change

可以用 * 导入所有名字

from foo import *
# 导入所有名字,与import不同,不用加前缀,所以容易混淆

__all__ :在foo.py中用 __all__ = [] 去控制*中得到的名字

循环导入

垃圾设计,但是我们要学会识别这种情况

被导入的模块 A 只会执行一次,如果在模块中导入别的模块 B 之后还有名字被定义,那么会先执行导入 B 模块的操作。如果B模块中又有导入A模块的操作,那么就不会再执行A模块了,而A模块中导入B模块下面的操作就不会执行,则报错

解决:将A中导入B的操作放到函数中,函数的定义阶段不会执行代码,就不会执行导入B的操作

模块的搜索路径优先级

模块本质上也是文件,无论是import还是from import,导入模块时都涉及到查找文件问题

查找的优先级:

  1. 内存(内置的模块)

  2. 从硬盘找:

    1. 按照sys.path中存放的文件的顺序依次查询要导入的模块

      import sys
      print(sys.path)
      # 运行文件所在文件夹的环境变量,值为一个列表,存放一系列的文件夹
      # 其中第一个文件夹是当前执行文件所在的文件夹
      # 第二个文件夹是当前pycharm项目的文件夹,pycharm帮你加的文件夹
      # 都找不到,则这种方法报错
      

可以通过sys中的方法可以看已经加载到内存中的模块

import sys
print(sys.modules)
# 环境变量是以执行文件为准的,所有的被导入的模块或者说后续的其他文件引用的sys.path都一样

python中有优化机制,因为申请模块的内存空间比申请变量的内存空间要大的多,所以python在程序运行中不会轻易回收模块的内存空间,del 模块名 都删除不了已经导入的模块

引用环境变量以外的模块

想要在sys.path以外别的地方放模块,可以这么做

import sys
sys.path.append(r'要添加的模块的绝对路径')
# 将要添加的文件夹加到环境变量中,那么在导入模块查找文件的时候就会找这个文件夹
import foo

编写模块应该遵循的规则

  1. 开头写模块的说明
  2. 尽量使用独立变量

补充函数的知识点

  1. 强类型 / 弱类型

    变量的数据类型一旦被定义,就不可以被改变,除非进行转化:python是强类型的语言

  2. 动态型 / 静态型

  3. python定义函数的时候在形参后面加冒号 数据类型可以对传入进行提示

    def index(name:'传入str',age:'传入数字'):
        pass
    
    # 函数的提示可以通过__anotations__()查看
    print(index.__annotations__())
    

什么是包

包就是一个包含有 __init__.py 文件的文件夹,包的本质是模块的一种形式

为何要包

包被当作模块导入

import bao
from bao import bun
# 和普通文件的模块用法一样

导入包,进行的三个步骤;

  1. 产生一个名称空间
  2. 运行包内的 __init__.py文件,将运行过程中产生的名字都丢到 1 的名称空间去
  3. 在当前执行文件所在的名称空间中得到一个名字 bao,该名字指向__init__.py的名称空间,导入包时并不会导入包下所有的子模块与子包

强调:

  1. python3,包中没有 __init__.py 也没事,python2中会报错
  2. 创建包的目的不是为了运行,而是被导入使用的

包中导入模块

要导入包中的模块,有以下几个方法

  1. 绝对导入:以包的文件夹作为起始来进行导入,在 __init__.py 中导入模块

    #__init__.py
    # 包名.模块名   模块中的名字
    from bao.m1 import f1
    from bao.m2 import f2
    from bao.m3 import f3
    # bao文件夹下,m1模块中的f1
    # bao文件夹下,m2模块中的f2
    # ...
    

    在使用包的时候,导入的环节和调用功能的方式一样

    import bao
    bao.f1()
    # bao包中m1模块下的f1
    

    导入包也可以用 from import语法,在执行程序的时候不用写前缀名:

    # 执行主文件中
    from bao import f1,f2,f3
    
    f1()
    f2()
    
  2. 相对导入:仅限于包内使用,不能跨出包

    # __init__.py
    # .代表当前文件夹
    # .. 代表上一层文件夹
    from .m1 import f1  # 当前文件夹下的m1的f1方法
    from .aaa.m4 import f1  # 当前文件夹下aaa文件夹下的m4中的方法f1
    

强调:导入过程中. 的,点的左边必须是包,可以有一连串的点,表示一连串的包嵌套

from a.b.c.e import xxx
import a.b.c.e
# .的左边必须是包
# a,b,c,e都是包

导入之后就没有左边必须是包的这种限制了

两种导入模式的优缺点:

  1. 绝对导入
    • 以顶级的包为起始,点的形式往下找子包,一定能找到
    • 更改包名或着模块名的时候,导入的方式全部要改变
    • 能够导入任意地方的包
  2. 相对导入
    • 包内模块彼此之间的导入,推荐使用相对导入
    • 当对包名更改时,因为只考虑在包内的相对位置,改的少
    • 不能跨出包

导入包也可以用 *

软件开发的目录规范

  • bin:存放程序中常用的自定义模块
  • config:配置文件
  • db:数据库相关的代码
  • lib:library,库,每部分公用的功能
  • core:核心代码的逻辑
  • api:接口
  • run:启动文件
  • setup:安装,部署,打包的脚本
  • requiments:存放软件依赖的外部数据
  • readme:说明文档
import os
print(__file__)
# 显示当前机器当前文件的绝对路径
print(os.path.dirname())
# 显示当前机器当前文件所在的文件夹名

通过这种方式获取当前文件的文件夹名,将他append进环境变量,这样在程序的所有的代码中,都可以调用父级文件夹下的模块

if __name__ == '__main__'
	src.run()

猜你喜欢

转载自www.cnblogs.com/telecasterfanclub/p/12590201.html