• 内置方法,序列化模块


    所有的作业讲解之后必须再敲一遍
    讲之后在写一遍

    反射
    hasattr
    getattr

      类名反射
          类名.静态属性  getattr(类名,"静态属性")
          对象名放射  getattr(类名,"类方法")()
          类名.静态方法() getattr(类名,"静态方法")()
          
          对象.对象属性 getattr(对象,"对象属性")
          对象.方法()  getattr(对象,"方法")
          模块名,方法
          模块名,类名
          模块名,变量
          模块名,函数
          
          本文件反射
          imp sys
          getattr(sys.modules[__name__]),所有定义在这个文件中的名字
    

    setattr 给命名空间的某一个名字设置一个值
    delattr 删除某一个命名空间中变量对应的值

    内置方法

    不用调用这个
    方法就可触发这个方法的执行
    __str__

    格式化输出 "%s" % obj
    print(obj)
    数据类型的强制转换
    

    __repr__ 当使用会触发str方法的方式但是Foo类内部又没有实现__str__方法时候都会调用__repr__

      '%r' % obj
      '!r'.format
      repr()
    

    作业总结

    购物车,是训练整段代码的驾驭能力,面向过程编程的使用
    员工信息系统,数据库系统原理的初识
    选课系统,面向对象编程的综合

    !!!note

    类的type都是type

    class A:pass
    print(type(A))
    -----------
    "输出"
    <class "type">
    -----------
    

    !!!

    fomat

    class A:
        name = "sfsd"
        def __repr__(self):
            return "bob"
        def __str__(self):
            return "b"
        def func(self):
            return "1"
    print("{}".format(A()))
    print("{.name}".format(A))
    print("{:,}".format(132545443))
    print("{:o}".format(8))
    print("{:x}".format(16))
    print("{:.2f}".format(43424.5435))
    print("{:a>20.4f}".format(234235.2342342))
    print("{1[1]},{0[0]}".format((1,34),(67,45)))
    print("{:+.3f}".format(23432444.23432))
    print("{sd},{va},{fd}".format(va="1",fd=67,sd="qwe"))
    emailf = "Your email address was {email}".format
    print(emailf(email="wodani@dd.com"))
    print("{}{{0}}".format("empty"))
    print("{!a}".format("牛逼"))
    print("{0:#d},{0:#x},{0:#b},{0:#o}".format(23))
    print(type(A))
    

    内置方法的进阶

    __new__
    __del__
    __len__
    __hash__
    __eq__

    __new__

    在init之前,实例化对象的第一步是__new__创造了一个空间
    python代码无法创建空间,创建空间交给了object.new()
    执行顺序

        实例化Foo,先执行__new__方法,
        但是Foo类没有__new__方法,
        到object类中去找先执行object中的__new__方法,
        开辟了一块属于对象的空间,
        才开始执行initself正式刚才创造的空间
    
    
    class Foo:
      def __init__(self): # 初始化方法
          print("执行了init") 
      def __new__(cls,*args,*kwargs):  # "构造方法"
          print("执行了new") 
          return object.__new__(cls)
        #return super().__new__(cls)
    obj = Foo()
    创造一个对象
    

    设计模式

    23种
    来自java
    单例模式

    "一个类只有一个实例的时候 单例模式"
    class Foo: pass
    obj1 = Foo()
    obj2 = Foo()
    
    class Foo:
      __instance =None
      def __init__(self):pass
      def __new__(cls,*args,*kwargs):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
          return cls.__instance
    obj1 = Foo("alex",20)
    obj2 = Foo("egon",22)
    

    __del__

    在删除这个类创建的对象的时候会先触发这个方法啊,再删除这个对象
    比如说关闭文件,关闭网络连接,关闭数据库

    class Foo:
      def __init__(self):
        self.age= age
        self.file = open("file",mode="w")
      def write(self):
        self.file.write("sdjfklsdjf")
      def __del__(self): #析构方法 
        self.file.close()
        print("执行了del了")
    

    __len__

    统计对象的长度

    
    class Classes:
      def __init__(self,name,course):
        self.name = name
        self.course = course
        self.students = []
      def __len__(self):
        return len(self.students)
    s1 = Class("歧视1班","python")
    s1.students.append("wuyi")
    s1.students.append("wangfan")
    print(len(s1))
    

    __eq__

    class Staff:
        def  __init__(self,name,sex):
          self.name = name
          self.sex = sex
        def __eq__(self,other):
          return self.name == other.name
          # return self.__dict__ == other.__dict__
    alex = Staff("alex","不详")
    alex2 = Staff("alex","不详")
    print(alex == alex2) #值判断
    print(alex is alex2) #身份判断
    
    
    

    __hash__ 哈希

    1. 每次执行hash值都会变化
    2. 再一次执行的过程中对同一个值得hash结果总是不变的
    class Foo():pass
    obj1 = Foo()
    obj2 = Foo()
    print(type(hash(obj1))) #int
    print(type(hash(obj2)))
    

    字典寻址快原因
    !!!error 溜号了没听明白
    !!!
    字典在内存中是如何存储的?
    为什么字典的key必须可hash?
    字典通过key转变的hash值直接找到内存中值的地址

    hash算法原理

    1. 对于相同的值在同一次程序的运行中是不会变化的
    2. 对于不同的值在一次程序的运行中总是不同的

    set的去重机制
    !!!error
    list去重需要遍历 并且in判断 时间 O(n)
    set = {1,2,3,4,5,6,7,8,9}
    不能通过逐个判断值相等这件事来做去重工作
    内存地址与值
    hash 1 1地址 1值
    hash 2 2地址 2值
    hash 2 得到结果地址由于也是2 但是里面有值,也就不去存储
    hash n 得到的值如果没有内存地址 那么表示没有新的值
    hash算法也不是完全靠谱
    如果也别长可能会相同
    如果刚好hash值一样,再做一个值得比对,如果值不相同,然后再对新的值二次寻址

    "面试题"
    > 员工类
    > 姓名 性别 年龄 部门
    > 转岗位
    > 姓名 年龄变化了 性别 部门  
    > 100个员工 去掉重复的
    > 员工的姓名和性别是相同的,就认为使用一个员工
    
    > 答案
    "通过重写__hash__以及__eq__对大列表去重"
    "得到了hash值相等了,但是set的机制是地址相同之后开始判断值是不是相同"
    "所以要通过eq方法过去"
    class Staff:
      def __init__(self,name,age,sex,dep):
        self.name = name
        self.age = age
        self.sex = sex
        self.dep = dep
      def __hash__(self):
        return hash(self.name+self.sex)
      def __eq__(self,other):
        if self.name == other.name and self.sex == other.sex:
            return True
    name_lst = ["yuanhao","egon","nazha","peqi"]
    obj_lst = []
    for i in range(100):
        name = name_lst[i%4]
        obj = Staff(name,i,"male","python")
        obj_lst.append(obj)
    print(obj_lst)
    ret = set(obj_lst)
    print(ret)
    for i in ret:
      print(i)
    
    1. 对每个元素进行hash计算出一个内存地址
    2. 到这个内存地址上查看
    3. 如果这块内存中没有值
    4. 将这个元素存到对应的内存地址上
    5. 如果这块内存中已经有值
    6. 判断这两个值时候相等
    7. 如果相等,就舍弃后面的值
    8. 如果不相等就二次须知再找一个新的内存空间
      !!!

    第二种用例是在动态执行环境中支持协作多重继承。
    super() 被实现为用于显式点属性查找(例如 super().getitem(name))的绑定过程的一部分。它通过实现自己的 getattribute() 方法来搜索类,以可预测的顺序支持合作多重继承。因此,super() 未定义用于使用诸如 super()[name] 的语句或操作符的隐式查找。

    内置方法的例子

    纸牌游戏
    面试题

    常用模块

    1. 序列化模块
    2. 随机数模块

    别人写好的功能放在一个文件里
    内置模块 安装python解释器时一起装上的。
    第三方模块,扩展模块:需要自己安装
    自定义模块:自己写了含有功能的。自己写的py文件

    序列化模块

    什么叫序列化
    序列
    字符串
    bytes

    把一个数据类型转换成字符串,bytes类型的过程就叫做序列化。

    为什么要把一个数据类型序列化了?
    当你需要把一个数据类型存储在文件中。
    当你需要把一个数据类型同过网络传输的时候

    不能用eval() 用户输入 ,文件读入,网络传入

    "不支持单引号"
    import json
    stu = {"name":"何青松","sex":"male"}
    ret = json.dumps(stu) #序列化
    d = json.loads(ret) #反序列化
    print(stu)
    print(ret)
    print(d)
    

    json的优点

    所有的语言都通用

    缺点

    只支持非常少的数据类型
    对数据类型的约束很苛刻
    字典的key必须是字符串
    只支持:数字 字符串 列表 字典 (元组会强转成列表)

    待实践 扩展 JSONEncoder

    pickle 模块

    import pickle
    stu = {"name":"何青松","sex":"male",1:("a","b")}
    ret = pickle.dumps(stu) #拿到的永远是字节
    print(ret)
    d = pickle.loads(ret)
    print(d,type(d)) #搞定了数字类型的key以及value为元组类型
    
    class Course():
      def __init__(self,name,price):
        self.name = name
        self.price = price
    python = Course("python",29800)
    ret = pickle.dumps(python)
    print(ret)
    p = pickle.loads(ret)
    print(p.name,p.price)
    
    "手动创建也需要单引号"
    stu = {"name":"何青松","sex":"male",1:("a","b")}
    str_dir1 =  json.dumps(dic,ensure_ascii=False) #可现实中文
    with open("json_file","w",encoding="utf8") as f:
      f.write(str_dir1)
    
    with open("json_file","r",encoding="utf8") as g:
        content = g.read()
    ret = json.loads(content)
    
    with open("json_file","w",encoding=utf8) as h:
    json.dump(stu,f)
    with open("json_file","w",encoding=utf8) as k:
    dic =  json.load(k)
    print(dic,dic["name"])
    

    能不能多次向一个文件中dump?
    可以多次dump但是不能多次load

    stu = {"name":"何青松","sex":"male",1:("a","b")}
    with open("json_file","w",encoding="utf8") as g:
      json.dump(dic,g,ensure_asii=False)
      json.dump(dic,g,ensure_asii=False)
      json.dump(dic,g,ensure_asii=False)
      json.dump(dic,g,ensure_asii=False)
    with open("json_file","r",encoding="utf8") as g:
      dic = json.load(f)
    

    有需求向文件中写入多个字典
    只能用dumps转化成字符串在一一添加和用loads一行行去空白加载

    def my_dumps(dic):
      with open("json_file","a",encoding="utf8") as f:
          for line in f:
            dic = json.loads(line.strip())
            print(dic["name"])      
      
    

    json
    可以在所有的语言中通用
    能够处理的数据类型非常有限
    在网络操作中以及多语言环境中,要传递字典,数字,字符串,列表等简单的数据类型
    json的字典非常苛刻:key必须是字符串,所有的的字符串必须用“”
    dumps dic/list str 序列化
    loads str dic/list 反序列化方法
    dump dic/list 文件 序列化方法
    load 文件 dic/list 反序列 多次dump进入文件中的数据不能多次load会报错
    ensureascii 希望序列化的中文显示为中文并且写到文件中

    pickle
    全是b,b不指定编码

    with open("pick_file","wb") as f:
      pickle.dump(python,f)
    with open("pick_file","rb") as f:
      course =  pickle.load(f)
    

    当他load时需要类存在
    dump
    load
    操作文件必须以b的形式打开
    在load时候如果这个要被load的内容不在内从中会被报错

    pickle 能不能多次dump?

    python = Course("python",29800)
    linux = Course("linux",29800)
    mysql = Course("sql",25800)
    def my_dump(course):
      with open ("picke","ab") as f:
            pickle.dump(course,f)
    my_dump(python)
    my_dump(linux)
    my_dump(mysql)
    "由于不知道什么时候取完需要识别异常"
    with open("pickle","rb") as f:
        while True:
          try:
            content = pickle.load(f)
            print(content.name)
          except EOFError:
              break
    

    pickle 支持多次dump和多次load,需要异常处理

    作业

    每次角色实例化通过类方法传name进去不会像我构建的那样影响__init__列表,我的列表只有name一个参数。,正常需要有多种字段的传入。

  • 相关阅读:
    Java面向对象
    JBCD技术
    初识数据库(其他数据库对象)
    初识数据库(TCL语句)
    初识数据库(分组函数)
    初识数据库(函数)
    初识数据库(数据类型)
    Java中的IO流
    Java中的线程
    Java中的集合
  • 原文地址:https://www.cnblogs.com/yonghuierming/p/9579693.html
Copyright © 2020-2023  润新知