033.Python面向对象_类补充_生命周期

无奋斗不青春

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈

分隔线

类&补充_生命周期

    • 生命周期
      • 概念
      • 涉及问题
      • 监听对象生命周期
        • `__new__` 方法
        • `__init__` 方法
        • `__del__` 方法
      • 生命周期案例
    • 内存管理机制
      • 存储方面
      • 垃圾回收方面
        • 引用计数机制
        • 垃圾回收机制
          • 主要作用
          • 底层实现原理(了解/难)
          • 垃圾回收时机(掌握&简单)
          • 循环引用解决办法

生命周期

概念

  • 生命周期指的是一个对象从诞生到消亡的过程
  • 当一个对象被创建时,会在内存中分配相应的内存空间进行存储
  • 当这个对象不在使用,为了节约内存,就会把这个对象释放

涉及问题

  • 如何监听一个对象的生命过程?
  • Python是如何掌控一个对象的生命?

监听对象生命周期

__new__ 方法
  • 当我们创建一个实例对象时,用于给这个实例对象分配内存的方法
  • 通过拦截这个方法,可以修改实例对象的创建过程。例如:单例设计模式
    # 对比示例
    class Person1(object):
        pass
    
    
    p1 = Person1()
    print(p1)            # 输出:<__main__.Person object at 0x000001F672F8F5E0>
    
    
    # __new__方法示例
    class Person2(object):
        def __new__(cls, *args, **kwargs):
            print('新建一个实例对象,被我拦截了')
    
    
    p2 = Person2()
    print(p2)            # 输出:新建一个实例对象,被我拦截了    None
    
__init__ 方法
  • 当实例对象被创建完成之后,会自动调用这个方法,并且将这个对象传递给self
  • 在这个方法中可以给这个创建好的对象增加一个额外的信息(如:属性)
  • 通过__new__方法拦截实例对象创建操作后,该方法也无法执行
    class Person(object):
        def __init__(self):
            print('对象初始化')
            self.name = '失心疯'
    
    
    p = Person()
    print(p.name)
    
    
    # 实例对象创建被拦截后,该方法也无法执行
    class Person(object):
        def __new__(cls, *args, **kwargs):
            print('新建实例对象,被拦截了')
            
        def __init__(self):
            print('对象初始化')
            self.name = '失心疯'
    
    
    p = Person()
    print(p.name)
    
    # 输出结果
    # Traceback (most recent call last):
    #   File "E:\StudyCode\Python\13-面向对象\18-生命周期.py", line 28, in <module>
    #     print(p.name)
    # AttributeError: 'NoneType' object has no attribute 'name'
    # 新建实例对象,被拦截了
    
__del__ 方法
  • 当对象被释放时,会自动调用这方法(如:通过del方法删除对象)
    class Person(object):
        # def __new__(cls, *args, **kwargs):
        #     print('新建实例对象,被拦截了')
    
        def __init__(self):
            print('对象初始化')
            self.name = '失心疯'
    
        def __del__(self):
            print('对象被释放了')
    
    
    p = Person()
    print(p.name)
    del p
    

生命周期案例

  • 要求:记录一下,当前这个时刻由Person类产生的实例对象有多少个
  • 实现:创建一个实例对象,计数+1,删除一个实例对象,计数-1
    personCount = 0
    
    class Person(object):
        def __init__(self):
            global personCount
            personCount += 1
            # print('创建实例对象 计数+1')
    
        def __del__(self):
            global personCount
            personCount -= 1
            # print('释放实例对象 计数-1')
    
    
    p1 = Person()
    p2 = Person()
    print('当前实例个数为:', personCount)      # 当前实例个数为: 2
    del p1
    print('当前实例个数为:', personCount)      # 当前实例个数为: 1
    
  • 这一段实现代码中有几个问题
    • 1、每次输出统计数量的时候都要重复写上print('当前实例个数为:', personCount)这一句,代码冗余
    • 2、用于计数的personCount变量是一个全局变量,在外部可以随意改变
    • 3、在类内部使用personCount变量时,都需要使用global关键字指定变量是全局变量
  • 解决方法:
  • 1、将重复性的操作封装成一个方法,每次要用的时候直接调用方法
  • 2、将全局变量定义成类属性(不定义成实例属性,是因为实例属性是分别记录各个实例对象的属性)
  • 示例代码优化
    class Person(object):
        personCount = 0
    
        def __init__(self):
            Person.personCount += 1
            # print('创建实例对象 计数+1')
    
        def __del__(self):
            self.__class__.personCount -= 1
            # print('释放实例对象 计数-1')
    
        @staticmethod   # 静态方法
        def count():
            print('当前实例个数为:', Person.personCount)
    
    
    p1 = Person()
    p2 = Person()
    Person.count()      # 当前实例个数为: 2
    
    Person.personCount = 100
    del p1
    Person.count()      # 当前实例个数为: 99
    
  • 优化后的代码中依然有一些问题
    • 1、这个类属性在外界通过类名.属性的方式依然可以对这个属性进行修改
  • 解决方法
    • 将这个类属性改成私有属性,外界就无法对这个属性进行修改了
  • 示例代码优化
    class Person(object):
        __personCount = 0
    
        def __init__(self):
            Person.__personCount += 1
            # print('创建实例对象 计数+1')
    
        def __del__(self):
            self.__class__.__personCount -= 1
            # print('释放实例对象 计数-1')
    
        @staticmethod   # 静态方法
        def count():
            print('当前实例个数为:', Person.__personCount)
    
    
    p1 = Person()
    p2 = Person()
    Person.count()      # 当前实例个数为: 2
    del p1
    Person.count()      # 当前实例个数为: 1
    
  • 在这一段代码中,依然可以进行优化
  • 在这个类中的静态方法def count()中用到了这个类,那么我们在定义这个方法的时候,就可以通过参数来接收一个类
  • 那么,就可以通过定义类方法来实现这个操作
    class Person(object):
        __personCount = 0
    
        def __init__(self):
            Person.__personCount += 1
            # print('创建实例对象 计数+1')
    
        def __del__(self):
            self.__class__.__personCount -= 1
            # print('释放实例对象 计数-1')
    
        @classmethod   # 类方法
        def count(cls):
            print('当前实例个数为:', cls.__personCount)
    
    
    p1 = Person()
    p2 = Person()
    Person.count()      # 当前实例个数为: 2
    del p1
    Person.count()      # 当前实例个数为: 1
    


内存管理机制

  • 在Python中,内存管理机制是引用计数机制和垃圾回收机制两套机制并行的
  • 垃圾回收机制解决循环引用的问题,但是引用计数机制效率更高

存储方面

  • 1、在Python中万物皆对象
    • 其他部分语言中存在基本数据类型和对象
    • Python不存在基本数据类型,int、float、bool、str等都是对象
  • 2、所有对象都会在内存中开辟一块空间进行存储
    • 会根据不同的类型一级内容,开辟不同的空间大小进行存储
    • 返回该控件的地址给外界接收(称为“引用”)没用与后续对这个对象的操作
    • 通过id(对象)函数可以获取指定对象的内存地址(10进制)
    • 通过hex(10进制内存地址)函数可以查看对应的16进制地址
  • 3、对于整数和短小的字符,Python会进行缓存处理,不会创建多个相同的对象
  • 4、容器对象存储的其他对象,仅仅是存储的其他对象的引用,并不是存储的其他对象本身

垃圾回收方面

引用计数机制
  • 概念

    • 一个对象会记录者自身被引用的个数
      • 每增加一个引用,这个对象的引用计数就会自动+1
      • 每减少一个引用,这个对象的引用计数就会自动-1
  • 查看引用计数

    • 可以通过sys模块中的getrefcount(对象)方法获取到指定对象的引用数
    • 调用这个函数的时候,这个对象作为参数被传递的时候就是被引用,所以统计出来的引用数会比实际的引用数大1
      import sys
      
      class Person(object):
          pass
      
      
      p1 = Person()                   # 引用个数:1
      print(sys.getrefcount(p1))      # 2,获取到的引用个数比实际的大1
      
      p2 = p1                         # 引用个数:2
      print(sys.getrefcount(p1))      # 3
      
      del p2                          # 引用个数:1
      print(sys.getrefcount(p1))      # 2
      
      del p1                          # p1对象被删除,后续就无法再通过p1进行查询操作
      print(sys.getrefcount(p1))      # 报错:NameError: name 'p1' is not defined
      
  • 引用计数发生改变的场景举例

  • 引用计数+1场景

    • 对象被创建时 p1 = Person()
    • 对象被引用时 p2 = p1
    • 对象被作为参数传入到一个函数中时 log(p1),引用计数会+2
      • 对象作为参数传入一个函数时,在函数内部会被两个属性引用(__globals__func_globals)
    • 对象作为一个元素存储到容器中时 l = [p1]
  • 引用计数-1场景

    • 对象的别名被现实销毁 del p1
    • 对象的别名被赋予新的对象 p1 = 123
    • 一个对象离开它的作用域
      • 一个函数执行完毕时,内部的局部变量关联的对象,它的引用会被释放
    • 对象所在的容器被销毁或者从容器中删除对象
  • 特殊场景-循环引用问题

  • 内存管理机制:当一个对象 被引用,引用计数+1,删除引用,引用计数-1;引用计数为0时,对象被自动释放

  • 循环引用:

    class Person(object):
        pass
    
    
    class Dog(object):
        pass
    
    
    p = Person()
    d = Dog()
    
    p.pet = d
    d.master = p
    
    del p
    del d
    
    • 在这里插入图片描述
    * 通过 p = Person() 实例化对象的时候,p 引用了 Person 的内存地址, Person 对象的引用计数+1,此时 Person 对象的引用计数=1
    * 通过 d = Dog() 实例化对象的时候, d 引用了 Dog 的内存地址, Dog 对象的引用计数+1,此时 Dog 对象的引用计数=1
    
    * 通过 p.pet = d 添加属性赋值, Person 对象的 pet 属性引用了 Dog 的内存地址, Dog 对象的引用计数再+1,此时 Dog 对象的引用计数=2
    * 通过 d.master = p 添加属性赋值, Dog 对象的 master 属性引用了 Person 的内存地址, Person 对象的引用计数再+1,此时 Person 对象的引用计数=2
    
    * 通过 del p 语句删除p实例对象,释放 Person 对象的一个引用, Person 对象的引用计数-1,此时 Person 对象的引用计数=1
    * 通过 del d 语句删除d实例对象,释放 Dog 对象的一个引用, Dog 对象的引用计数-1,此时 Dog 对象的引用计数=1
    
    * 此时已经没有变量引用 Person和Dog对象了,这两个对象就没办法被使用了,但是他们的引用计数依然保存着1,就不会被释放掉,就造成了内存泄漏
    * 这两个对象之间属于互相引用的关系,就成了循环引用,导致两个对象的引用计数都是1,所以不能被引用计数机制释放
    
  • 由于实例对象被删除之后,无法使用sys.getrefcount获取对象的引用计数,需要通过第三方库objgraphcount方法来查看垃圾回收器,跟踪的对象个数

    • 安装第三方库objgraph
      pip install objgraph
      
    • 使用第三方库跟踪对象个数
      # 没有被循环引用的情况
      import objgraph
      
      
      class Person(object):
          pass
      
      
      class Dog(object):
          pass
      
      
      p = Person()
      d = Dog()
      print(objgraph.count('Person'))     # 追踪关于Person这个类的相关对象个数:1(也就是由Person类创建的实例对象个数)
      print(objgraph.count('Dog'))        # 追踪关于Dog这个类的相关对象个数:1(也就是由Dog类创建的实例对象个数)
      
      
      del p
      del d
      print(objgraph.count('Person'))     # p实例对象被删除,Person类相关的对象个数:0
      print(objgraph.count('Dog'))        # d实例对象被删除,Dog类相关的对象个数:0
      
      
      #==================================================
      
      # 被循环引用之后的情况
      import objgraph
      
      
      class Person(object):
          pass
      
      
      class Dog(object):
          pass
      
      
      p = Person()
      d = Dog()
      print(objgraph.count('Person'))     # 追踪关于Person这个类的相关对象个数:1(也就是由Person类创建的实例对象个数)
      print(objgraph.count('Dog'))        # 追踪关于Dog这个类的相关对象个数:1(也就是由Dog类创建的实例对象个数)
      
      p.pet = d
      d.master = p
      
      del p
      del d
      print(objgraph.count('Person'))     # p实例对象被删除,但是被Dog类的master属性引用,Person类相关的对象个数:1
      print(objgraph.count('Dog'))        # d实例对象被删除,但是被Person类的pet属性引用,Dog类相关的对象个数:1
      
垃圾回收机制
  • 垃圾回收机制:是属于引用计数机制的一个补充机制(一般对象完全可以通过引用计数机制进行释放,但是如果对象被循环引用,就无法通过引用计数机制进行释放,所以就产生了垃圾回收机制)
主要作用
  • 从经历过“引用计数机制”仍未被释放的对象中,找到“循环引用”并且干掉相关对象
底层实现原理(了解/难)
  • 怎样找到“循环引用”?

    • 1、收集所有的“容器对象”,通过一个双向链表进行记录引用
      • 容器对象:可以引用其他对象的对象(列表、元组、字典、自定义类对象等可以添加其他对象的东西)
      • 非容器对象:不可以引用其他对象的对象(int、float、bool、str等不能添加其他对象的对象)<非容器对象不能引用其他对象,所以就不会出现循环引用的情况>
      • 双向链表:
    • 2、针对每一个“容器对象”,通过一个变量gc_refs来记录当前对应的引用计数
    • 3、针对每个“容器对象”,找到他引用的“容器对象”,并将这个引用的“容器对象”的引用计数-1
    • 4、经过步骤3之后,如果一个“容器对象”的引用计数为0,就代表这个“容器对象”可以被回收了,肯定是“循环引用”导致他活到现在的
    • 在这里插入图片描述
  • 如何提升查找“循环引用”的性能

  • 上面这种垃圾回收的检测机制需要把所有记录在双向链表中的“容器对象”进行检测一遍,是非常的耗费性能。

  • 基于这个问题,Python就提出了一个假设:命越大,越长寿

    • 假设一个对象经过10次检测都没有被释放掉,那就认定这个对象一定很长寿,就减少对这个对象的“检测频率”
  • 基于这种假设,就设计了一套机制:分代回收

  • 分代回收

    • 1、默认一个对象被创建出来之后,属于0代
    • 2、如果经历过这一代“垃圾回收”之后,依然没有被释放,则划分到下一代
    • 3、“垃圾回收”的周期
      • 0代“垃圾回收”一定次数,会触发0代和1代回收
      • 1代“垃圾回收”一定次数,会触发0代、1代和2代回收
    • 在这里插入图片描述
  • 垃圾回收器当中,新增的对象个数-消亡的对象个数,达到一定的阈值时,才会触发垃圾检测

  • 个人理解:当出现循环引用对象(无法被释放的对象)个数达到一定阈值时候才会触发垃圾检测

  • 查看和设置相关参数

  • 语法

    import gc
    
    gc.get_threshold()          # 查看触发机制的阈值
    # 输出 (700, 10, 10)
    # 700   触发垃圾检测的阈值
    # 10    触发0代和1代回收的阈值
    # 10    触发0代、1代和2代回收的阈值
    
    gc.set_threshold(触发垃圾检测的阈值,触发0代和1代回收的阈值,触发0代、1代和2代的阈值)
    # 设置触发阈值
    
  • 示例代码

    import gc
    
    print(gc.get_threshold())           # 输出:(700, 10, 10)
    # 700   垃圾回收器中, 新增对象个数 - 消亡对象个数 = 700,触发垃圾检测
    # 10    每经过10次【0代垃圾回收】检测,就触发一次【0代和1代回收】(前面10次仅执行0代回收)
    # 10    每经过10次【0代和1代垃圾回收】检测,就触发一次【0代、1代和2代回收】
    # 10次【0代回收】执行1次【0代和1代回收】,10次【0代和1代回收】执行1次【0代、1代和2代回收】
    
    gc.set_threshold(1000, 50, 20)
    # 1000   设置垃圾回收器中, 新增对象个数 - 消亡对象个数 = 1000时,才触发垃圾检测
    # 50     设置每经过50次【0代垃圾回收】检测,就触发一次【0代和1代回收】
    # 20      设置每经过20次【0代和1代垃圾回收】检测,就触发一次【0代、1代和2代回收】
    
    print(gc.get_threshold())           # 输出:(1000, 50, 20)
    
垃圾回收时机(掌握&简单)
  • 自动回收
  • 触发条件:开启垃圾回收机制并且达到了垃圾回收的阈值
  • 阈值:垃圾回收器中,新增的对象个数 与 释放的对象个数 之差
  • 垃圾回收机制开启和关闭设置
    import gc
    
    gc.enable()         # 开启垃圾回收机制(默认开启)
    gc.disable()        # 关闭垃圾回收机制
    gc.isenabled()      # 判定垃圾回收机制是否开启状态
    
  • 垃圾回收阈值获取和设置
    import gc
    
    gc.get_threshold()      # 获取自动回收阈值
    gc.set)threshold()      # 设置自动回收阈值
    
  • 手动回收
  • 语法
    import gc
    
    gc.collect(garbage=None)    # 运行垃圾收集器
        # garbage:可以是一个整数,指定要收集哪一代,默认运行完整收集(0代、1代、2代)
    
    # 无论垃圾回收机制是否开启,都可以运行
    
  • 示例(循环引用问题解决)
    # 默认情况,出现循环引用后无法被引用计数机制释放,未达到阈值的情况下也不会被垃圾回收机制释放
    import objgraph
    
    
    class Person(object):
        pass
    
    
    class Dog(object):
        pass
    
    
    p = Person()
    d = Dog()
    
    p.pet = d
    d.master = p
    
    del p
    del d
    
    print(objgraph.count('Person'))      # 输出:1
    print(objgraph.count('Dog'))         # 输出:1
    
    
    #=============通过手动开启垃圾回收机制进行释放=========================
    
    import objgraph
    import gc
    
    
    class Person(object):
        pass
    
    
    class Dog(object):
        pass
    
    
    p = Person()
    d = Dog()
    
    p.pet = d
    d.master = p
    
    del p
    del d
    
    gc.collect()                        # 手动开启垃圾回收机制
    
    print(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    
    
循环引用解决办法
  • 可到达引用:可以直接访问真实对象的引用(p 和 d)
  • 不可到达引用:需要通过可到达引用间接的访问真实对象(pet 和 master)
    • 不能直接通过pet和master访问真实对象,必须通过p.pet和d.master间接访问,删除p和d之后,就无法通过pet和master访问到真实对象了
  • 强引用:会影响对象的引用计数的引用
  • 弱引用:与强引用相对,弱引用并不会影响对象的引用计数,也就是说其不影响对象是否被回收的判定(需要使用weakref模块)
  • 基础类型int、list、dict、tuple、str不支持弱引用,对其执行弱引用会报错
  • 可以通过__weakrefoffset__查看类型是否支持弱引用,该变量表示弱引用指针相对对象起始地址的偏移量,>0表示支持弱引用
  • weakref模块
  • 方法
    weakref.ref(obj)                    # 给指定对象创建一个弱引用
    weakref.WeakKeyDictionary(dict)     # 给指定字典的key创建一个弱引用
    weakref.WeakValueDictionary(dict)   # 给指定字典的value创建一个弱引用
    
  • 通过使用弱引用解决循环引用不能自动释放问题
    import objgraph
    import weakref
    
    
    class Person(object):
        pass
    
    
    class Dog(object):
        pass
    
    
    p = Person()
    d = Dog()
    
    p.pet = d
    d.master = weakref.ref(p)       # 通过weakref.ref进行弱引用
    
    del p
    del d
    
    
    print(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    
  • 当一个对象引用多个对象时,可以使用字典的方式
    import objgraph
    import weakref
    
    
    class Person(object):
        pass
    
    
    class Dog(object):
        pass
    
    class Cat(object):
        pass
    
    
    p = Person()
    d = Dog()
    c = Cat()
    
    # p.pet = {'Dog': d, 'Cat': c}
    p.pet = weakref.WeakValueDictionary({'Dog': d, 'Cat': c})
    d.master = p
    
    del p
    del d
    del c
    
    
    print(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    print(objgraph.count('Cat'))         # 输出:0
    
  • 在释放对象之前打断循环引用
    import objgraph
    
    
    class Person(object):
        pass
    
    
    class Dog(object):
        pass
    
    
    p = Person()
    d = Dog()
    
    p.pet = d
    d.master = p
    
    p.pet = None
    del p
    del d
    
    
    print(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/188547.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java学习路径:入门学习、深入学习、核心技术,操作案例和实际代码示例

学习路径&#xff1a;入门学习、深入学习、核心技术&#xff0c; 每个主题都包括很多的操作案例和实际代码示例。 a. 入门学习&#xff1a; 1. 基础语法&#xff1a; 变量和数据类型&#xff1a; // 定义和初始化变量 int age 25;// 不同数据类型的声明 double price 19.99…

智能汽车十大网络安全攻击场景-《智能汽车网络安全权威指南》

引言 大家都很熟悉OWASP Top 10风险报告&#xff0c;这个报告不但总结了Web应用程序最可能、最常见、最危险的10大安全隐患&#xff0c;还包括了如何消除这些隐患的建议&#xff0c;这个“OWASP Top 10“差不多每隔三年更新一次。目前汽车网络安全攻击威胁隐患繁多&#xff0c…

AI绘画“湿地公园的美女”

1、AI绘画&#xff1a;湿地公园的美女 通过输入描述&#xff1a;你需要什么场景的什么创作内容&#xff0c;AI根据内容创造出适合的主题 如图所示&#xff1a;请帮我创作一个湿地公园的像高圆圆的美女图片。 输出的结果如下&#xff1a;总体来说感觉还是非常快&#xff0c;基…

python pip安装第三方包时报错 error: Microsoft Visual C++ 14.0 or greater is required.

文章目录 1.问题2.原因3.解决办法 1.问题 pip install 的时候报错一大堆&#xff0c;其中有这么一段话 &#x1f447; error: Microsoft Visual C 14.0 or greater is required. Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visua…

Proteus仿真--用DS1302与12864LCD设计的可调式中文电子日历

本文主要介绍用DS1302和12864 LCD的可调式中文电子日历&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真图如下 其中12864LCD上面显示中文年月日信息时间信息&#xff0c;按键K1-K4&#xff0c;K1用于年月日时分选择&#xff0c;K2用于加功能&#xff0c;K3用于…

基于时隙的多重冗余流指纹模型

文章信息 论文题目&#xff1a;基于时隙的多重冗余流指纹模型 期刊&#xff08;会议&#xff09;&#xff1a;网络与信息安全学报 时间&#xff1a;2023 级别&#xff1a;CCF C 概述 为确保内生网络流量安全可信&#xff0c;本文在研究流水印及其扩展的流指纹机制的基础上&a…

Docker的学习笔记

1.1 docker的介绍 1.2 docker的一次安装 //如果是root用户&#xff0c;不加sudo也行curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg | sudo apt-key add -echo deb https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/ buster stable…

【限流配电开关】TPS2001C

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评百大…

软件开发中的抓大放小vs极致细节思维

最近在开发过程中&#xff0c;遇到了好多次 “这个需求点这次要不要做&#xff1f;” 的问题&#xff0c; 主要有两方阵营&#xff0c;比如以研发主导的 “这次先不做、等必要的时候再做” &#xff0c;另外一方是以PM主导的 “这个不做需求不完整&#xff0c;可能影响用户体验…

Cortex-M与RISC-V区别

环境 Cortex-M以STM32H750为代表&#xff0c;RISC-V以芯来为代表 RTOS版本为RT-Thread 4.1.1 寄存器 RISC-V 常用汇编 RISC-V 关于STORE x4, 4(sp)这种寄存器前面带数字的写法&#xff0c;其意思为将x4的值存入sp4这个地址&#xff0c;即前面的数字表示偏移的意思 反之LOA…

使用Pytorch从零开始构建GRU

门控循环单元 (GRU) 是 LSTM 的更新版本。让我们揭开这个网络的面纱并探索这两个兄弟姐妹之间的差异。 您听说过 GRU 吗&#xff1f;门控循环单元&#xff08;GRU&#xff09;是更流行的长短期记忆&#xff08;LSTM&#xff09;网络的弟弟&#xff0c;也是循环神经网络&#x…

LoadRunner压力测试实例

摘要&#xff1a;本文通过实例讲解介绍了LoadRunner 工具的使用&#xff0c;介于公司的实际情况&#xff0c;文中主要是对工具的基本使用做了详细描述&#xff0c;高级运用方面除性能计数器与参数设置外其它均未涉及&#xff0c;待以后补充。目的是使公司人员根据该手册便可以独…

服务器被入侵了怎么去排查

在当今数字化时代&#xff0c;网络安全问题变得越来越重要。其中&#xff0c;服务器被入侵是一种常见的安全威胁。当服务器被入侵时&#xff0c;我们需要采取一系列措施来排查和解决问题。本文将为您提供服务器被入侵后的排查步骤。 第一步&#xff1a;确认服务器被入侵 当发现…

动手学深度学习(四)---多层感知机

文章目录 一、理论知识1.感知机2.XOR问题3.多层感知机4.多层感知机的从零开始实现 【相关总结】1.torch.randn()2.torch.zeros_like() 一、理论知识 1.感知机 给定输入x,权重w&#xff0c;和偏移b,感知机输出&#xff1a; 2.XOR问题 感知机不能拟合XOR问题&#xff0c;他…

2023年最新IntelliJ IDEA下载安装以及Java环境搭建教程(含Java入门教程)

文章目录 写在前面Java简介IntelliJ IDEA简介IntelliJ IDEA下载安装JDK简介JDK下载教程 Java入门IntelliJ IDEA使用教程 写在后面 写在前面 2023年最新IntelliJ IDEA下载安装教程&#xff0c;内含JAVA环境搭建教程&#xff0c;一起来看看吧&#xff01; Java简介 Java是一门…

MySQL的基础知识

目录 关系型数据库 SQL通用语法 数据类型 数值类型 字符串类型 日期类型 SQL分类 DDL 数据库操作 表操作 DML 添加数据 修改数据 删除数据 DQL 基本查询 条件查询 聚合函数 分组查询 排序查询 分页查询 执行顺序 DCL 管理用户 权限控制 函数 字符串…

模型优化【2】-剪枝[局部剪枝]

模型剪枝是一种常见的模型压缩技术&#xff0c;它可以通过去除模型中不必要的参数和结构来减小模型的大小和计算量&#xff0c;从而提高模型的效率和速度。在 PyTorch 中&#xff0c;我们可以使用一些库和工具来实现模型剪枝。 pytorch实现剪枝的思路是生成一个掩码&#xff0…

如何学习VBA:3.2.8 OnTime方法与OnKey方法

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的劳动效率&#xff0c;而且可以提高数据处理的准确度。我推出的VBA系列教程共九套和一部VBA汉英手册&#xff0c;现在已经全部完成&#xff0c;希望大家利用、学习。 如果…

基于51单片机的人体追踪可控的电风扇系统

**单片机设计介绍&#xff0c; 基于51单片机超声波测距汽车避障系统 文章目录 一 概要概述硬件组成工作原理优势应用场景总结 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 # 基于51单片机的人体追踪可控的电风扇系统介绍 概述 该系统是基于51…

Flink实战(11)-Exactly-Once语义之两阶段提交

0 大纲 [Apache Flink]2017年12月发布的1.4.0版本开始&#xff0c;为流计算引入里程碑特性&#xff1a;TwoPhaseCommitSinkFunction。它提取了两阶段提交协议的通用逻辑&#xff0c;使得通过Flink来构建端到端的Exactly-Once程序成为可能。同时支持&#xff1a; 数据源&#…