zoukankan      html  css  js  c++  java
  • 序列化模块、导入模块

    序列化

    序列化:将原本的字典、列表等内容转换成字符串的过程就叫做序列化

    序列化的目的:
      1.以某种存储形式使自定义对象持久化
      2.将对象从一个地方传递到另一个地方
      3.使程序更具维护性

    序列化:从数据类型 --> 字符串的过程
    反序列化:从字符串 --> 数据类型的过程

    用于序列化的模块:jsonpickleshelve

    json
      通用的序列化格式,通过json,不同编程语言之间可以互相识别;

    pickle
      pickle序列化的内容只有python能理解,且部分反序列化依赖python代码;
      所有的python中的数据类型都可以转化成字符串形式

    shelve:
      序列化句柄
      使用句柄直接操作,非常方便

    json模块

    提供了四个功能:dumps、dump、loads、load
    可序列化数据类型:数字、字符串、列表、字典、元组(通过转换成列表再序列化)

    import json
    
    dic = {1: "a", 2: "b"}
    
    dic_d = json.dumps(dic)    # 序列化
    print(dic_d, type(dic_d))  # {"1": "a", "2": "b"} <class 'str'>
    
    dic_l = json.loads(dic_d)  # 反序列化
    print(dic_l, type(dic_l))  # {"1": "a", "2": "b"} <class 'str'>

    dump、load:必须打开一个文件再操作,一次性写进去,一次性读出来

    dic = {1: "a", 2: "b"}
    with open("1.txt", "w", encoding="utf-8") as f:
        json.dump(dic, f)
    
    with open("1.txt", "r", encoding="utf-8") as f:
        ret = json.load(f)
        print(ret, type(ret))  # {'1': 'a', '2': 'b'} <class 'dict'>

    对于中文:序列化时添加参数 ensure_ascii=False

    dic = {1: "你好", 2: "世界"}
    ret = json.dumps(dic, ensure_ascii=False)
    print(ret, type(ret))  # {"1": "你好", "2": "世界"} <class 'str'>
    
    with open("1.txt", "w", encoding="utf-8") as f:
        json.dump(dic, f, ensure_ascii=False)
    
    with open("1.txt", "r", encoding="utf-8") as f:
        ret = json.load(f)
        print(ret, type(ret))  # {'2': '世界', '1': '你好'} <class 'dict'>

    pickle模块

    用于python特有的类型和python的数据类型间进行转换

    pickle模块提供了四个功能:dumps/dump(序列化,存)、loads(反序列化,读)、load(不仅可以序列化字典、列表...可以把python中任意的数据类型序列化)

    import pickle
    
    dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
    str_dic = pickle.dumps(dic)
    print(str_dic)  # bytes数据类型
    
    dic2 = pickle.loads(str_dic)
    print(dic2)    #{'k3': 'v3', 'k2': 'v2', 'k1': 'v1'}
    import pickle
    import time
    
    struct_time = time.localtime(1000000000)
    print(struct_time)    #time.struct_time(tm_year=2001, tm_mon=9, tm_mday=9, tm_hour=9, tm_min=46, tm_sec=40, tm_wday=6, tm_yday=252, tm_isdst=0)
    f = open('pickle_file', 'wb')
    pickle.dump(struct_time, f)
    f.close()
    
    f = open('pickle_file', 'rb')
    struct_time2 = pickle.load(f)
    print(struct_time2.tm_year)    #2001

    shelve模块:

    import shelve
    
    f = shelve.open('shelve_file')
    f['key'] = {'int': 10, 'float': 9.5, 'string': 'Sample data'}  # 直接对文件句柄操作,就可以存入数据
    f.close()
    
    f1 = shelve.open('shelve_file')
    existing = f1['key']    #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
    f1.close()
    print(existing)    #{'string': 'Sample data', 'int': 10, 'float': 9.5}

    模块的导入

    模块的导入顺序:
      内置模块
      扩展模块
      自定义模块

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

    import sys
    print(sys.modules)  # 结果是一个字典

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

    当要导入模块时,就依据sys.path路径寻找需要导入的模块

    import sys
    print(sys.path)
    
    #['E:\study_python', 'E:\study_python', 'E:\study_python\venv\Scripts\python35.zip', 'C:\Python35\DLLs', 'C:\Python35\lib', 'C:\Python35', 'E:\study_python\venv', 'E:\study_python\venv\lib\site-packages', 'E:\study_python\venv\lib\site-packages\setuptools-39.1.0-py3.5.egg', 'E:\study_python\venv\lib\site-packages\pip-10.0.1-py3.5.egg', 'D:\PyCharm201814\helpers\pycharm_matplotlib_backend']
    View Code
    # 导入的函数func,会被当前位置定义的read覆盖
    from demo import func
    
    def func():
        print("本地的func")
    func()  # 本地的func

    from...import *(这种方式非常不安全,慎用)

    #demo里的代码如下:
    def read():
        print("demo里的read")
    money = 100
    
    
    #money没有使用demo里的值,而是使用了当前名称的值,所以非常不安全,慎用*这种导入模式
    from demo import *
    money = 200
    print(money)    #200 --> 模块里的money方法将永远被覆盖
    read()    #demo里的read
    
    
    #而 import demo 不会出现这种情况,因为要使用money,就得用demo.money格式
    import demo
    money = 200
    print(money)    #200 --> 当前的值
    print(demo.money)    #100 --> 模块的值

    from...import * 模式中的 __all__ 的作用,只有带 * 这种模式才会有 __all__

    # demo.py
    __all__ = ["func1", "func2"]
    
    def func1():
        print("func1")
    
    def func2():
        print("func2")
    
    ########################################

    # test.py # 然后使用 from demo import * 就只能导入 func1 和 func2 方法啦 from demo import * func1() # func1 func2() # func2

    如果demo.py中的名字前加 _ ,如_func1,则采用 from demo import * 时,_func1 不能被导入

    import 与 from...import... 区别

    import
    导入模块格式:
        import 模块名
            如何使用:模块名.变量名
            和本文件中的变量名完全不冲突
        import 模块名 as 自定义模块名
        import 模块名1,模块名2
            导入多个模块
    
    from ... import ...
    导入模块格式:
        from 模块名 import 变量名
            如何使用:直接操作"变量名"
            如果本文件中有相同的变量名会发生冲突
        from 模块名 import 变量名 as 自定义变量名
        from 模块名 import 变量名1,变量名2
            从同一个模块导入多个功能
        from 模块名 import *
            将模块中的所有变量名都导入进来,但是那些由单一下划线 _开头的名字不在此例;大多数情况下,python程序员不使用这种方法,因为引入其他来源的命名,很可能覆盖了已有的定义
            如果本文件中有相同的变量名会发生冲突

     __name__ 属性

    一个模块被另一个程序第一次引入时,其主程序将运行;如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用 __name__ 属性来使该程序块仅在该模块自身运行时执行。

    # demo.py
    
    if __name__ == "__main__":
       print("程序自身在运行")
    else:
       print("我来自另一模块")

     运行结果:

    import demo
    # 我来自另一模块
    demo.py
    # 程序自身在运行
  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/believepd/p/9623052.html
Copyright © 2011-2022 走看看