• day21


    1. 模块

    1.1 什么是模块?
        # 模块是已经写好的一组功能的集合
        # 别人写好的函数 变量 方法 放在一个文件里 (这个文件可以被我们直接使用)这个文件就是一个模块
        # 模块可以是:py文件 dll文件 zip文件
    
    1.2 如何自己写一个模块
        # 创建一个py文件,给它起一个符合变量名命名规则的名字,这个名字就是模块名

     2. 模块的导入

    2.1 import 模块名
        假设有在同级目录下有一个my_module.py文件
        my_module.py:
        ------------------------------
            print(12345)
    
            name = 'alex'
    
            def read1():
                print('in read1 func')
    
            def read2():
                print("in read2 func", name)
    
            print(54321)
        ------------------------------
        # 在导入模块的过程中发生了什么?
            import my_module
            结果: 12345
                    54321
    
        总结:导入一个模块就是执行一个模块
    
        # 怎么使用my_module模块中的名字
        print(my_module.name)  # alex
        print(my_module.read1)  # <function read1 at 0x0000017D5B7E9510>
        my_module.read1()  # in read1 func
    
        # improt的命名空间,模块和当前文件在不同的命名空间中
        name = 'egon'
        def read1():
            print("main read1")
    
        print(name)  # egon
        print(my_module.name)  # alex
    
        # 模块只能用自己命名空间的变量,不能用当前空间的,因为没有执行关系
        name = 'egon'
        def read1():
            print("main read1")
    
        print(name)  # egon
        print(my_module.name)  # alex
        my_module.read2()  # in read2 func alex
    
        总结:每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
        ---------------------------------------
        # 模块是否可以被重复导入?
        import my_module
        import my_module
        结果: 13245
              54321
    
        总结:第一次导入后就将模块名加载到内存,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句。
    
        # 怎么判断这个模块已经被导入过了???
        import sys
        print(sys.modules)
    
        # 模块导入的过程中发生了什么?
        # 找到这个模块
        # 判断这个模块是否被导入过了
        # 如果没有导入过
            # 创建一个属于这个模块的命名空间
            # 让模块的名字 指向 这个空间
            # 执行这个模块中的代码
        ------------------------------------
        # 给模块起别名,起了别名之后,使用这个模块就都使用别名引用变量了
        import my_module as m  # 12345 54321
        m.read1()  # in read1 func
    
        # json pickle
        # dumps loads
        def func(dic, t = 'json'):
            if t == 'json':
                import json
                return json.dumps(dic)
            elif t == 'pickle':
                import pickle
                return pickle.dumps(dic)
        # 直接用别名,简化代码
        def func(dic, t = 'json'):
            if t == 'json':
                import json as aaa
            elif t == 'pickle':
                import pickle as aaa
            return aaa.dumps(dic)
        -----------------------------------
        # 导入多个模块/分别起别名
            import os,time
            import os as o,time as t
    
        # 规范建议 模块应该一个一个的导入: 内置模块,第三方模块,自定义模块
    
        # 所以导入模块是有顺序的:
            # 内置模块
            # 扩展(第三方模块)
            # 自定义模块
    
        # 大家都符合这个规范,是为了大家用彼此模块很方便
        # import os
    
        # import django
    
        # import my_module
    2.2 模块的导入from import
        # 如何使用 from import?
            # 需要从一个文件中使用哪个名字,就把这个名字导入进来
            # from my_module import name
    
        # from import的过程中仍然会执行了这个被导入的文件
        -------------------------------------------------------------
        # import谁就只能用谁
        from my_module import read1  # 第一次导入,创建命名空间,执行这个文件,找到要导入的变量,创建引用指向要导入的变量.
        read1()  # in read1 func 这里只导入了read1,所以只能用read
    
        # 想要使用read2,还要再导入read2
        from my_module import read2  # 上面已经导入过,所以直接找到要导入的变量,创建引用指向要导入的变量.
        read2()  # in read2 func alex
        --------------------------------------------------------------------
        # 覆盖问题
        from my_module import read1  # 第一次被导入,创建命名空间,执行,找到变量,创建引用指向要导入的变量
        def read1():  # 这里重新定义了read1,所以导入进来的模块中的read1倍覆盖
            print("in my read1")
        read1()  # in my read1
    
        from my_module import read2  # 已经被导入过,直接找到变量,创建引用指向要导入的变量
        read2()  # in read2 func alex
        --------------------------------------------------------------
        # 一行导入多个名字?
        from my_module import read1, read2  # 12345 54321
        read1()  # in read1 func
        read2()  # in read2 func alex
        -------------------------------------------------------------------
        # 给导入的名字起别名
        from my_module import read1 as r1, read2 as r2
         read1():
            print("in my read1")
        r1()  # in read1 func
        r2()  # in read2 func alex
        read1()  # in my read1
        ------------------------------------------------------------------
        # from my_module import * 在导入的过程中 内存的引用变化
        from my_module import *  # 导入my_module.py文件中的所有成员
        name = 'egon'  # name被覆盖
        print(name)  # egon
        read1()
        read2()  # 用的是自己空间的alex
        ----------------------------------------------------------------
        # * 和 __all__  __all__能够约束*导入变量的内容
        修改:在my_module.py文件的上面加上一行__all__ = ['name']
        from my_module import *  # 12345 54321
        print(name)  # alex
        read1()  # 报错
        read2()  # 报错
    
        # __all__ 只能约束*

    3. 模块中引用的情况

    3.1 模块的循环引用 ☆☆☆
        # 模块之间不允许循环引用
        # 比如以下这些情况:
    
    
    
    
    
    

       模块a和模块b的引用构成了一个循环

    3.2 模块的加载与修改 ☆
        ------------------------------------------
        import time  # 导入时间模块
        import my_module  # 导入my_module.py文件,此时read1函数里是打印111
        
        time.sleep(10)  # 程序在这里停止10s,假设我在这里修改了打印为222
        my_module.read1()  # 那么这里打印的还是111,因为导入的时候已经存在于内存当中了,你修改的是文件里面的,你修改不了内存
    
        总结: 已经被导入的模块发生了修改,是不会被感知到的
        ----------------------------------------------------
        import time  # 导入时间模块
        import importlib
        import my_module  # 导入my_module.py文件,此时read1函数里是打印111
    
        time.sleep(10)  # # 程序在这里停止10s,假设我在这里修改read1函数打印的为222
        importlib.reload(my_module)  # 重新导入模块my_module,此时内容已经被修改
        my_module.read1()  # 所以此时read1打印的是222
    
        总结: 要想修改的模块被正在运行中的程序感知到,重启这个程序(或者重新加载模块)
    3.3 把模块当初脚本执行 ☆☆☆☆☆
        # 执行一个py文件的方式:
            # 在cmd里执行/在pycharm执行: 直接执行这个文件 - 以脚本的形式运行这个文件
            # 导入这个文件
        
        # 都是py文件
            # 直接运行这个文件 这个文件就是一个脚本
            # 导入这个文件   这个文件就是一个模块
    
        有calculate.py文件,里面是一个计算器
        -----------------------------------------------
        def main(exp):
            exp = exp.replace(' ', '')
            while 1:
                ret = re.search('([^()]+)', exp)
                if ret:
                    inner_backet = ret.group()
                    res = str(cal(inner_backet))
                    exp = exp.replace(inner_backet, res)
                    exp = format_exp(exp)
                else:
                    break
            return cal(exp)
    
        s = input(">>>")
        print(main(s))
        -------------------------------------------------
        假设我直接执行这个文件,此时它是脚本,它可以独立的提供一个功能
        但是假设我从同级目录的文件导入它,此时它是一个模块,能够被导入者调用这个功能,会先执行交互,但是我们不需要这个交互
        
        # 当一个py文件
        # 当做一个脚本的时候: 能够独立的提供一个功能,能自主完成交互
        # 当成一个模块的时候: 能够被导入者调用这个功能,不能自主交互
    
    # 一个文件中的__name__变量
        # 当这个文件被当做脚本执行的时候 __name__ == '__main__'
        # 当这个文件被当前模块导入的时候 __name__ == '模块的名字'
    
        这时我们可以用__name__ 来完成脚本和模块的需求
        将    if __name__ == '__main__':
                   s = input(">>>")
                   print(main(s))    放在calculate.py文件的最下面,
        当我们直接执行这个文件时,如果__name__等于'__main__',就可以执行交互,else:当它被当做模块导入时,__name__等于'模块的名字'
        此时calculate.py文件为
        ------------------------------------------
            def main(exp):
            exp = exp.replace(' ', '')
            while 1:
                ret = re.search('([^()]+)', exp)
                if ret:
                    inner_backet = ret.group()
                    res = str(cal(inner_backet))
                    exp = exp.replace(inner_backet, res)
                    exp = format_exp(exp)
                else:
                    break
            return cal(exp)
        if __name__ == '__main__'
            s = input(">>>")
            print(main(s))
    3.4 模块搜索路径 ☆☆☆☆☆
        # 和被当做脚本执行的文件 同目录下的文件 可以直接被导入
            因为被当做脚本直接执行这个文件,模块搜索路径中有这个文件的所在的目录,所有这个文件同级的模块可以被直接导入,因为他们的目录都一样
    
        # 除此之外其他路径下的模块 在被导入的时候需要自己修改sys.path列表

     4. 包

    4.1 什么是包?
        # 包: 文件夹中有一个__init__.py文件
        # 包: 是几个模块的集合
    
    4.2 包的导入语句
        
        # import  从包当中导入模块
        # import glance2.api.policy
        # glance2.api.policy.get()
        
        # import glance2.api.policy as policy
        # policy.get()
        
        # from import  导入模块,或者导入模块中的方法
        # from glance2.api import policy
        # policy.get()
        
        # from glance2.api.policy import get
        # get()
    
        # 关于包相关的导入语句也分为import和from ... import ...两种,但    是无论哪种,无论在什么位置,
        # 在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。
    
        # 需要注意的是from后import导入的模块,必须是明确的一个不能带点,
        # 否则会有语法错误,如:from a import b.c是错误语法
    4.3 绝对导入/相对导入
        (1)直接导入包
            # 导入一个包
                # 不意味着这个包下面的所有的内容都是可以被使用的
                # 导入一个包到底发生了什么?
                # 相当于执行了这个包下面的__init__.py文件
    
        (2)绝对导入
            # 绝对导入:
            # 优点:
                # 在执行一个python脚本的时候,这个脚本以及和这个脚本同级的模块只能用绝对导入
            # 缺点:
                # 所有的导入都要从一个根目录下往后解释文件夹之间的关系
                # 是是如果当前导入包的文件和被导入的包的位置发生了变化,那么所有init文件都要做相应的调整
    
        (3)相对导入
            # 相对导入
            # 优点:
                # 不需要去反复的修改路径
                    # 只要一个包中的所有文件夹和文件的相对位置不发生改变
                # 也不需要去关心当前这个包和被执行文件之间的层级关系
            # 缺点:
                # 含有相对导入的py文件不能被直接执行
                # 必须放在包中被导入的调用才能正常执行
    
        # 如果只是从包中导入模块的话,那么我们不需要做任何多余的操作
        # 直接导入就行了
    
        # 如果我们希望导入包的时候,能够顺便把模块也导进来
        # 需要设计init文件
        # 绝对目录的导入相对目录的导入各有千秋
  • 相关阅读:
    mkdir命令
    pwd命令
    chmod命令
    chown命令
    chgrp命令
    687. Longest Univalue Path
    HYSBZ 1036 树的统计Count (水题树链剖分)
    POJ 3709 K-Anonymous Sequence (斜率优化DP)
    LightOJ 1065 Island of Survival (概率DP?)
    LightOJ 1248 Dice (III) (水题,期望DP)
  • 原文地址:https://www.cnblogs.com/kangqi452/p/11509070.html
Copyright © 2020-2023  润新知