zoukankan      html  css  js  c++  java
  • 模块导入和包

    模块

    import

    一个模块就是一个包含了Python定义和声明的文件,文件名就是模块名字加上.py的后缀

    模块的使用:假如自定义一个模块my_moudle.py,文件名my_moudle.py,模块名my_moudle

     1 #my_moudle.py
     2 print('from the my_moudle.py')
     3 
     4 money=1000
     5 
     6 def read1():
     7     print('my_moudle->read1->money',money)
     8 
     9 def read2():
    10     print('my_moudle->read2 calling read1')
    11     read1()
    12 
    13 def change():
    14     global money
    15     money=0
    my_moudle模块

    模块的引用:针对同一模块的多次使用,Python为了防止多次重复导入,Python会增加一系列的优化:第一次导入后就将模块名加载到内存了,后续的import语句只是对加载到内存的模块的一次引用,不会重新执行模块内的语句

     1 #demo.py
     2 import my_moudle #只在第一次导入时才执行my_moudle.py内代码,此处的显式效果是只打印一次'from the my_moudle.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.
     3 import my_moudle
     4 import my_moudle
     5 import my_moudle
     6 
     7 '''
     8 执行结果:
     9 from the my_moudle.py
    10 '''
    demo.py

    我们可以从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。

     每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突

     1 #测试一:money与my_moudle.money不冲突
     2 #demo.py
     3 import my_moudle 
     4 money=10
     5 print(my_moudle.money)
     6 
     7 '''
     8 执行结果:
     9 from the my_moudle.py
    10 '''
    11 测试一:money与my_moudle.money不冲突
    模块之间的冲突

    首次导入模块会做一下三件事:

    1.为源文件(my_moudle模块)创建新的名称空间,在my_moudle中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
    
    2.在新创建的命名空间中执行模块中包含的代码,见初始导入import my_moudle
    
    3.创建名字my_moudle来引用该命名空间

    为模块起别名:

    1 import my_moudle as sm
    2 print(sm.money)
    

     为模块起别名,根据用户的输入选择不同的功能

    #mysql.py
    def sqlparse():
        print('from mysql sqlparse')
    #oracle.py
    def sqlparse():
        print('from oracle sqlparse')
    
    #test.py
    db_type=input('>>: ')
    if db_type == 'mysql':
        import mysql as db
    elif db_type == 'oracle':
        import oracle as db
    
    db.sqlparse() 
    起别名进化版
    1 if file_format == 'xml':
    2      import xmlreader as reader
    3 elif file_format == 'csv':
    4      import csvreader as reader
    5 data=reader.read_date(filename)
    超级进化版

    from.(父模块名)..import..(子模块名)...

    这样导入模块可以导入你需要的,对于不需要的不加载(个人见解,原创(#^.^#))

    如果对于导入的模块有重名会发生覆盖效果

     1 #demo.py
     2 from my_moudle import read1
     3 def read1():
     4     print('==========')
     5 read1()
     6 '''
     7 执行结果:
     8 from the my_moudle.py
     9 ==========
    10 '''
    模块的覆盖

    Python中的变量赋值只是一种绑定关系,而不是存储操作(就好比a=7,是把a与,7暂时绑定,让a代替7干想干的事,而不是说a就是7,a只能存储7这个数据《原创(~ ̄▽ ̄)~》)

     1 from my_moudle import money,read1
     2 money=100 #将当前位置的名字money绑定到了100
     3 print(money) #打印当前的名字
     4 read1() #读取my_moudle.py中的名字money,仍然为1000
     5 
     6 '''
     7 from the my_moudle.py
     8 100
     9 my_moudle->read1->money 1000
    10 '''
    拓展拓展

    和文件操作类似,也支持as

    1 from my_moudle import read1 as read

    支持导入多行

    1 from my_moudle import (read1,
    2                   read2,
    3                   money)
    

    from my_moudle import * 把my_moudle中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。

    __all__=['money','read1'] #这样在另外一个文件中用from my_moudle import *就这能导入列表中规定的两个名字
    *如果my_moudle.py中的名字前加_,即_money,则from my_moudle import *,则_money不能被导入

    把模块当做脚本执行

     即Python文件可以在cmd命令提示符下边当做脚本,
    
    __name__在谁的工作目录下调用返回的是谁的结果
    
    (假如我自己调用自己的模块返回的是我自己的模块名,其他人调用返回的是他自己的)
    
    魔铠的查找顺序:内存中加载的,内置模块,sys.path路径中包含的模块
    
    查找模块内的所有子模块名(dir(模块名))

    包(存在于一个文件夹中的模块的集合)

     1 执行文件为test.py,内容
     2 #test.py
     3 import aaa
     4 同级目录下创建目录aaa,然后自建空__init__.py(或者干脆建包)
     5 需求:验证导入包就是在导入包下的__init__.py
     6     先执行看结果
     7     再在__init__.py添加打印信息后,重新执行
     8 需求:
     9 aaa.x
    10 aaa.y
    11 解决:在__init__.py中定义名字x和y
    12 在aaa下建立m1.py和m2.py
    13 #m1.py
    14 def f1():
    15     print('from 1')
    16 #m2.py
    17 def f2():
    18     print('from 2')
    19 需求:
    20 aaa.m1 #进而aaa.m1.func1()
    21 aaa.m2 #进而aaa.m2.func2()
    22 
    23 解决:在__init__.py中定义名字m1和m2,先定义一个普通变量,再引出如何导入模块名
    24 在aaa下新建包bbb
    25 需求:
    26 aaa.bbb
    27 
    28 解决在aaa的__init__.py内导入名字bbb
    29 在bbb下建立模块m3.py
    30 #m3.py
    31 def f3():
    32     print('from 3')
    33 需求:
    34 aaa.bbb.m3 #进而aaa.bbb.m3.f3()
    35 
    36 解决:是bbb下的名字m3,因而要在bbb的__init__.py文件中导入名字m3
    37 绝对导入变成相对导入
    38 需求:
    39 aaa.m1()
    40 aaa.m2()
    41 aaa.m3()
    42 
    43 解决:在aaa的__init__.py中拿到名字m1、m2、m3
    44 包内模块直接的相对导入,强调包的本质:包内的模块是用来被导入的,而不是被执行的
    45 用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护
    46 将包整理当做一个模块,移动到别的目录下,操作sys.path
    小孩子不能看哟
    1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
    2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
    3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
    强调:
      1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
          2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块

    两个包A和B,假如AB里边都有a模块,他们也不会冲突(处于两个命名空间)

    绝对到导入和相对导入:

    绝对导入:以该包的根目录作为起始
    
    相对导入:用.或者..的方式作为起始(只能在一个包内使用)(可以在包的同级文件下测试)
    特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。
    

     单独导入包名称是不会导入包中的所有子模块

    模块与包之间的调用:

    在同一工作目录下用一个文件里调用另一个包里的内容可以采用import的方式,超过三层一般就会不适用,模块里文件的相互调用一般在两层以内
  • 相关阅读:
    ArcMap和ArcGIS Pro加载百度地图
    智能家居系列之——WIFI小车
    关于GIS中Scale和Resolution的那些事儿
    git cherry-pick
    虚拟DOM与DOM diff
    变量提升
    如果判定 this 又混乱了,就从头再读一遍……
    js 高程 Array
    Js高程-DOM
    剑指 Offer 15. 二进制中1的个数
  • 原文地址:https://www.cnblogs.com/52-qq/p/7325900.html
Copyright © 2011-2022 走看看