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

无奋斗不青春

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

分隔线

类&补充_生命周期

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

生命周期

概念

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

涉及问题

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

监听对象生命周期

__new__ 方法
  • 当我们创建一个实例对象时,用于给这个实例对象分配内存的方法
  • 通过拦截这个方法,可以修改实例对象的创建过程。例如:单例设计模式
    # 对比示例
    class Person1(object):passp1 = 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 = 0class Person(object):def __init__(self):global personCountpersonCount += 1# print('创建实例对象 计数+1')def __del__(self):global personCountpersonCount -= 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 = 0def __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()      # 当前实例个数为: 2Person.personCount = 100
    del p1
    Person.count()      # 当前实例个数为: 99
    
  • 优化后的代码中依然有一些问题
    • 1、这个类属性在外界通过类名.属性的方式依然可以对这个属性进行修改
  • 解决方法
    • 将这个类属性改成私有属性,外界就无法对这个属性进行修改了
  • 示例代码优化
    class Person(object):__personCount = 0def __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 = 0def __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 sysclass Person(object):passp1 = Person()                   # 引用个数:1
      print(sys.getrefcount(p1))      # 2,获取到的引用个数比实际的大1p2 = p1                         # 引用个数:2
      print(sys.getrefcount(p1))      # 3del p2                          # 引用个数:1
      print(sys.getrefcount(p1))      # 2del 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):passclass Dog(object):passp = Person()
    d = Dog()p.pet = d
    d.master = pdel 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 objgraphclass Person(object):passclass Dog(object):passp = 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 objgraphclass Person(object):passclass Dog(object):passp = Person()
      d = Dog()
      print(objgraph.count('Person'))     # 追踪关于Person这个类的相关对象个数:1(也就是由Person类创建的实例对象个数)
      print(objgraph.count('Dog'))        # 追踪关于Dog这个类的相关对象个数:1(也就是由Dog类创建的实例对象个数)p.pet = d
      d.master = pdel 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 gcgc.get_threshold()          # 查看触发机制的阈值
    # 输出 (700, 10, 10)
    # 700   触发垃圾检测的阈值
    # 10    触发0代和1代回收的阈值
    # 10    触发0代、1代和2代回收的阈值gc.set_threshold(触发垃圾检测的阈值,触发0代和1代回收的阈值,触发0代、1代和2代的阈值)
    # 设置触发阈值
    
  • 示例代码

    import gcprint(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 gcgc.enable()         # 开启垃圾回收机制(默认开启)
    gc.disable()        # 关闭垃圾回收机制
    gc.isenabled()      # 判定垃圾回收机制是否开启状态
    
  • 垃圾回收阈值获取和设置
    import gcgc.get_threshold()      # 获取自动回收阈值
    gc.set)threshold()      # 设置自动回收阈值
    
  • 手动回收
  • 语法
    import gcgc.collect(garbage=None)    # 运行垃圾收集器# garbage:可以是一个整数,指定要收集哪一代,默认运行完整收集(0代、1代、2代)# 无论垃圾回收机制是否开启,都可以运行
    
  • 示例(循环引用问题解决)
    # 默认情况,出现循环引用后无法被引用计数机制释放,未达到阈值的情况下也不会被垃圾回收机制释放
    import objgraphclass Person(object):passclass Dog(object):passp = Person()
    d = Dog()p.pet = d
    d.master = pdel p
    del dprint(objgraph.count('Person'))      # 输出:1
    print(objgraph.count('Dog'))         # 输出:1#=============通过手动开启垃圾回收机制进行释放=========================import objgraph
    import gcclass Person(object):passclass Dog(object):passp = Person()
    d = Dog()p.pet = d
    d.master = pdel p
    del dgc.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 weakrefclass Person(object):passclass Dog(object):passp = Person()
    d = Dog()p.pet = d
    d.master = weakref.ref(p)       # 通过weakref.ref进行弱引用del p
    del dprint(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    
  • 当一个对象引用多个对象时,可以使用字典的方式
    import objgraph
    import weakrefclass Person(object):passclass Dog(object):passclass Cat(object):passp = Person()
    d = Dog()
    c = Cat()# p.pet = {'Dog': d, 'Cat': c}
    p.pet = weakref.WeakValueDictionary({'Dog': d, 'Cat': c})
    d.master = pdel p
    del d
    del cprint(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    print(objgraph.count('Cat'))         # 输出:0
    
  • 在释放对象之前打断循环引用
    import objgraphclass Person(object):passclass Dog(object):passp = Person()
    d = Dog()p.pet = d
    d.master = pp.pet = None
    del p
    del dprint(objgraph.count('Person'))      # 输出:0
    print(objgraph.count('Dog'))         # 输出:0
    

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[NOIP2006]明明的随机数

一、题目 登录—专业IT笔试面试备考平台_牛客网 二、代码 set去重&#xff0c;再利用vector进行排序 std::set是一个自带排序功能的容器&#xff0c;它已经按照一定的规则&#xff08;默认是元素的小于比较&#xff09;对元素进行了排序。因此&#xff0c;你不能直接对std::s…

【JAVA杂货铺】一文带你走进面向对象编程|继承|重载|重写|期末复习系列 | (中4)

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:Java学习系列专栏&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 继承 私有成员变量在继承中的使用​编辑 当子类和父类变量不重名时: 当子类和父类重名时: &#x1f4dd;总结: 继承的含义: …

卷积神经网络经典backbone

特征提取是数据分析和机器学习中的基本概念&#xff0c;是将原始数据转换为更适合分析或建模的格式过程中的关键步骤。特征&#xff0c;也称为变量或属性&#xff0c;是我们用来进行预测、对对象进行分类或从数据中获取见解的数据点的特定特征或属性。 1.AlexNet paper&#…

jQuery_06 过滤器的使用

什么是过滤器&#xff1f; 过滤器就是用来筛选dom对象的&#xff0c;过滤器是和选择器一起使用的。在选择了dom对象后在进行过滤筛选。 jQuery对象中存储的dom对象顺序与页面标签声明有关系。 声明顺序就是dom中存放的顺序 1.基本过滤器 使用dom对象在数组中的位置来作为过滤条…

一网打尽异步神器CompletableFuture

Future接口以及它的局限性 我们都知道&#xff0c;Java中创建线程的方式主要有两种方式&#xff0c;继承Thread或者实现Runnable接口。但是这两种都是有一个共同的缺点&#xff0c;那就是都无法获取到线程执行的结果&#xff0c;也就是没有返回值。于是在JDK1.5 以后为了解决这…

FloodFill

"绝境之中才窥见&#xff0c;Winner&#xff0c;Winner" FloodFill算法简介: floodfill又翻译成漫水填充。我们可以将下面的矩阵理解为一片具有一定高度的坡地&#xff0c;此时突发洪水&#xff0c;洪水会将高度<0的地方填满。 话句话来说&#xff0c;Fl…

IDEA2023版本创建Sping项目只能勾选17和21,却无法使用Java8?(已解决)

文章目录 前言分析解决方案一&#xff1a;替换创建项目的源方案二&#xff1a;升级JDK版本 参考文献 前言 起因 想创建一个springboot的项目&#xff0c;本地安装的是1.8&#xff0c;但是在使用Spring Initializr创建项目时&#xff0c;发现版本只有17和21。 在JDK为1.8的情况下…

代码随想录算法训练营第四十六天【动态规划part08】 | 139.单词拆分、背包总结

139.单词拆分 题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 求解思路&#xff1a; 单词是物品&#xff0c;字符串s是背包&#xff0c;单词能否组成字符串s&#xff0c;就是问物品能不能把背包装满。 动规五部曲 确定dp数…

弹窗concrt140.dll丢失的解决方法,深度解析concrt140.dll丢失的原因

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示或者系统崩溃的情况。其中&#xff0c;concrt140.dll是一个常见的错误提示&#xff0c;这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;本文将介绍5种详细的解决方法&#xff0c;帮助您恢…

蓝桥杯官网算法赛(蓝桥小课堂)

问题描述 蓝桥小课堂开课啦&#xff01; 海伦公式&#xff08;Herons formula&#xff09;&#xff0c;也称为海伦-秦九韶公式&#xff0c;是用于计算三角形面积的一种公式&#xff0c;它可以通过三条边的长度来确定三角形的面积&#xff0c;而无需知道三角形的高度。 海伦公…

有理数比较

【问题描述】编写函数CompareRational()&#xff0c;比较两个有理数的大学&#xff0c;该函数的参数为两个有理数&#xff08;结构体类型&#xff0c;包含分子分母两个整数&#xff09;&#xff0c;若第一个有理数小于第二个&#xff0c;返回一个负数&#xff1b;若相等&#x…

Python 进阶(十):数学计算(math 模块)

《Python入门核心技术》专栏总目录・点这里 文章目录 1. 导入math模块2. 常用数学函数3. 常量4. 其他函数和用法5. 总结 大家好&#xff0c;我是水滴~~ Python的math模块提供了许多数学运算函数&#xff0c;为开发者在数值计算和数据处理方面提供了强大的工具。本教程将详细介…

【100个Cocos实例】看完这个,我再也不要当赌狗了...

引言 探索游戏开发中抽奖转盘的奥秘。 抽奖转盘是一种常见的互动元素&#xff0c;通常用于游戏、营销活动等场景。 本文将介绍一下抽奖转盘的原理和实现。 本文源工程可在文末阅读原文获取&#xff0c;小伙伴们自行前往。 1.抽奖转盘的组成 抽奖转盘的实现涉及多个组成部分…

基于springboot校园车辆管理系统

背景 伴随着社会经济的快速发展&#xff0c;机动车保有量不断增加。不断提高的大众生活水平以及人们不断增长的自主出行需求&#xff0c;人们对汽车的 依赖性在不断增强。汽车已经发展成为公众日常出行的一种重要的交通工具。在如此形势下&#xff0c;高校校园内的机动车数量也…

【KubeSphere】基于AWS在 Linux 上以 All-in-One 模式安装 KubeSphere

文章目录 一、实验配置说明二、实验准备工作1.确认系统版本2. 修改网络DNS3. 关闭SELINUX4. 关闭防火墙 三、实验依赖项安装四、下载 KubeKey五、一键化安装部署六、验证安装结果七、登录KubeSphere管理控制台八、参考链接 一、实验配置说明 本实验基于AWS启动一台新实例&…

I/O多路转接之epoll

承接上文 I/O多路转接之poll-CSDN博客 简介 epoll的相关系统调用 epoll底层原理 编写epoll的server 重新回归一下epoll原理&#xff0c;LT&#xff0c;ET epoll改成ET工作模式 -- 初识(有bug) epoll初识 按照man手册的说法: 是为处理大批量句柄而作了改进的poll. 它是在2.5.4…

CANdelaStudio 使用教程4 编辑State

文章目录 简述1、State Groups2、Dependencies3、 Defaults State1、 会话状态2、 新增会话状态3、 编辑 服务对 State 的依赖关系 State Diagram 简述 1、State Groups 2、Dependencies 在这里&#xff0c;可以编辑现有服务在不同会话状态或安全访问状态的支持情况和状态转换…

python每日一题——7接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表…

粒子群算法Particle Swarm Optimization (PSO)的定义,应用优点和缺点的总结!!

文章目录 前言一、粒子群算法的定义二、粒子群算法的应用三、粒子群算法的优点四、粒子群算法的缺点&#xff1a;粒子群算法的总结 前言 粒子群算法是一种基于群体协作的随机搜索算法&#xff0c;通过模拟鸟群觅食行为而发展起来。该算法最初是由Eberhart博士和Kennedy博士于1…

概念解析 | 玻尔兹曼机

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:玻尔兹曼机。 概念解析 | 玻尔兹曼机 引言 随着人工智能技术的飞速发展,玻尔兹曼机作为一种重要的生成模型,受到了广泛的关注。 背景介绍 玻尔兹曼机(Boltzmann Machine)是一…