第二章对象模型(3):从创建到销毁,对象的生命周期

C++面试必懂知识:C++对象的生命周期详细解读 在C++中,作用域是一个非常重要的概念,它直接关系到对象的生命周期。作用域决定了对象存在的时间范围,也就是说,对象在作用域内被创建,并在作用域结束时被销毁(特别是对于自动对象而言)。因此,深入理解作用域是掌握对象生命周期管理的关键。作用域有多种类型,包括局部作用域、全局作用域、命名空间作用域和类作用域等。局部作用域是最常见的一种,它通常与代码块相关联。当一个对象在函数内部或任何代码块内部被定义时,它就具有局部作用域。这种对象被称为局部变量或自动变量,它们在进入作用域时自动创建,并在离开作用域时自动销毁。 阅读详情

1. 对象的创建

首先我们需要观察思考:
  • Python 内部是如何从无到有创建一个浮点对象的
  • Python 又是怎么知道该如何将它打印到屏幕上的呢?
>>> pi = 3.14

>>> print(pi)
3.14

下面以 floatl类型为例子,对应C实体是 PyFloat_Type
  • 首先来介绍C API

  • Python 是用 C 写成的,对外提供了 C API ,让用户可以从 C 环境中与其交互。 Python 内部也大量使用这些 API ,为了更好研读源码,先系统了解 API 组成结构很有必要。 C API 分为两类: 泛型 API 以及 特型 API 。

    • (1)泛型 API
      • 泛型 API 与类型无关,属于 抽象对象层 ( Abstract Object Layer ),简称 AOL 。 这类 API 参数是 PyObject* ,可处理任意类型的对象, API 内部根据对象类型区别处理
      • 我的理解就是通用的接口, 就像人一样,每个人都需要 吃饭,睡觉。 吃饭,睡觉,就是泛型API,处理任意类型的对象(人),所谓抽象,就是不是具体指某个实际对象,而是抽提出来的公共部分,所称为 抽象。(看过java基础,对抽象类概念的理解)
      • 以对象打印函数为例子:
int
PyObject_Print(PyObject *op, FILE *fp, int flags)

接口第一个参数为待打印对象,可以是任意类型的对象,因此参数类型是 PyObject* 。 Python 内部一般都是通过 PyObject* 引用对象,以达到泛型化的目的
* 对于任意类型的对象,均可调用 PyObject_Print 将其打印出来(抽象)

// 打印浮点对象
PyObject *fo = PyFloatObject_FromDouble(3.14);
PyObject_Print(fo, stdout, 0);

// 打印整数对象
PyObject *lo = PyFloatObject_FromLong(100);
PyObject_Print(lo, stdout, 0);

PyObject_Print 接口内部根据对象类型,决定如何输出对象。

  • (2)特型 API
    • 特型 API 与类型相关,属于 具体对象层 ( Concrete Object Layer ),简称 COL 。 这类 API 只能作用于某种类型的对象,例如浮点对象 PyFloatObject 。 Python 内部为每一种内置对象提供了这样一组 API
    • 很容易理解,就是针对 某个类型,提供特定的方法接口。
      例如:
PyObject *
PyFloat_FromDouble(double fval)

PyFloat_FromDouble 创建一个浮点对象,并将它初始化为给定值 fval 。


对象的创建
到这里我们终于要讲对象的创建了! 当然前面的介绍是少不了的
  • 经过上面一节的学习,我们知道了 元数据的概念,它保存在类型对象中。
    • 1.元数据 保存着创建对象的 内存等在这里插入代码片信息。
    • 2.支持的操作 。
    • 3 也包括对象如何创建的信息。
  • 实际上,不管创建爱你对象的流程如何,最终的关键步骤都是 分配内存。
总结起来python内部通过两种方式创建对象
  • (1)通过 C API ,例如 PyFloat_FromDouble ,多用于内建类型;比如 上面提到的 float
  • (2) 通过类型对象,例如 Dog ,多用于自定义类型
  • 通过类型对象创建实例对象,是一个更通用的流程(大部分创建多使用这个方法),同时支持内置类型和自定义类型。 以创建浮点对象为例,我们还可以通过浮点类型 PyFloat_Type 来创建:例如
>>> pi = float('3.14')
>>> pi
3.14

2.对象的调用及多态性

(1)可调用对象:
  • 上面通过调用 类型对象的方式创出来的一个实例 pi, 这就说明对象是可调用的
  • 对象被调用时,执行的函数肯定是定义在了类型当中,那里保存着实例对象(类型对象之前所过,也是被type实例的 实例对象)的元信息
  • 所以再type中(PyType_Type):找到一个字段:tp_call
PyTypeObject PyType_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "type",                                     /* tp_name */
    sizeof(PyHeapTypeObject),                   /* tp_basicsize */
    sizeof(PyMemberDef),                        /* tp_itemsize */

    // ...
    (ternaryfunc)type_call,                     /* tp_call */

    // ...
};

我们知道了,当实例对象被调用时,便执行 tp_call 字段保存的处理函数。!这就是 python对象调用当中,底层C中的实现!!!

  • 因此 float(‘3.14’) 在 C 层面等价于:
PyFloat_Type.ob_type.tp_call(&PyFloat_Type, args, kwargs)
1. 首先浮点类型对象 ,调用ob_type字段对应的 类型: PyType_Type
2. 调用其中的tp_call, 完成对象的调用


即:
PyType_Type.tp_call(&PyFloat_Type, args, kwargs)


最终执行, type_call 函数:
type_call(&PyFloat_Type, args, kwargs)

书作者:调用参数通过 args 和 kwargs 两个对象传递,先不展开,留到函数机制中详细介绍。

  • 下面我们开始看type_call 函数,定义于 Include/typeobject.c ,关键代码如下
static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PyObject *obj;

    // ...
    obj = type->tp_new(type, args, kwds);
    obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
    if (obj == NULL)
        return NULL;

    // ...
    type = Py_TYPE(obj);
    if (type->tp_init != NULL) {
        int res = type->tp_init(obj, args, kwds);
        if (res < 0) {
            assert(PyErr_Occurred());
            Py_DECREF(obj);
            obj = NULL;
        }
        else {
            assert(!PyErr_Occurred());
        }
    }
    return obj;
}
  • 不懂C语言没关系,只要能看懂大概:
    *(1)调用类型对象 tp_new 函数指针 申请内存 (第 7 行);
    • (2)必要时调用类型对象 tp_init 函数指针对对象进行 初始化 (第 15 行)
到这里对象的创建过程已经十分清晰了!

在这里插入图片描述
总结一下:

  • 调用 float (这里类型对象创建实例), Python 最终执行其类型对象 type 的 tp_call 函数;
  • tp_call 函数调用 float 的 tp_new 函数为实例对象分配 内存空间
  • tp_call 函数必要时进一步调用 tp_init 函数对实例对象进行 初始化
(2)对象的多态性实现
  • 首先,要实现多态性,首先要明白什么是多态!我找到一篇文章,里面例子介绍什么是多态,希望 认真观看:https://baijiahao.baidu.com/s?id=1646997242602110678&wfr=spider&for=pc
  • 面相对象程序设计的三大特性:封装性,继承性,多态性!
  • 我的理解,多态性,先从这个词理解就是:多种形态, 指的就是一个类型的属性或方法在子类中表现为不同的形态,既多种形态。就像上面的链接中的例子:多态性的应用实例, 我们三次执行时,调用的都是父类的同一个方法:construct(), 而传入的参数不同,父类会调用不同的 子类方法实现。
那么内部C语言层面上具体是如何进行实现多态性的呢?
  • 类似于上面所说的,Python 创建一个对象,比如 PyFloatObject ,会分配内存,并进行初始化。 此后, Python 内部统一通过一个 PyObject* 变量来保存和维护这个对象,而不是通过 PyFloatObject* 变量
  • 通过PyObject* 变量保存和维护对象,可以实现更抽象的上层逻辑,而不用关心对象的实际类型和实现细节。也就是泛型。抽象的,任何实际类型都可以传入,并完成对应的保存和维护。
  • 文中提到:以对象哈希值计算为例,假设有这样一个函数接口:
Py_hash_t
PyObject_Hash(PyObject *v);
// 该函数可以计算任意对象的哈希值,不管对象类型是啥。 例如,计算浮点对象哈希值:

PyObject *fo = PyFloatObject_FromDouble(3.14);
PyObject_Hash(fo);

// 对于其他类型,例如整数对象,也是一样的:
PyObject *lo = PyLongObject_FromLong(100);
PyObject_Hash(lo);
  • 可以看到上面的例子,一个函数,可以解决所有类型的对象求hash值的操作,答案在Object/object.c中
Py_hash_t
PyObject_Hash(PyObject *v)
{
    PyTypeObject *tp = Py_TYPE(v);
    if (tp->tp_hash != NULL)
        return (*tp->tp_hash)(v);
    /* To keep to the general practice that inheriting
    * solely from object in C code should work without
    * an explicit call to PyType_Ready, we implicitly call
    * PyType_Ready here and then check the tp_hash slot again
    */
    if (tp->tp_dict == NULL) {
        if (PyType_Ready(tp) < 0)
            return -1;
        if (tp->tp_hash != NULL)
            return (*tp->tp_hash)(v);
    }
    /* Otherwise, the object can't be hashed */
    return PyObject_HashNotImplemented(v);
}
  • 首先函数通过ob_type 指针找到对象的类型 (第 4 行)
  • 然后通过类型对象的 tp_hash 函数指针,调用对应的哈希值计算函数 (第 6 行)。
  • 也就是说: PyObject_Hash 根据对象的类型,调用不同的函数版本!! 这不就是多态吗?! 类似于上面链接中讲的例子,根据传入的实例对象不同,而调用对象的相对应方法完成操作! 这就是通过 ob_type 字段, Python 在 C 语言层面实现了对象的 多态 特性!
对象的行为
  • 我们上面的一节 通过提出两个问题说过,对象的 元数据保存在 类型对象中,并且规定了对象的 行为,既操作。
  • 不同对象的行为不同,比如哈希值计算方法就不同,由类型对象中 tp_hash 字段决定。 除了 tp_hash ,我们看到 PyTypeObject 结构体还定义了很多函数指针,这些指针最终都会指向某个函数,或者为空。 这些函数指针可以看做是 类型对象 中定义的 操作 ,这些操作决定对应 实例对象 在运行时的 行为 。
  • 然而,除了对象特有的行为,不同对象还会有一些共性:比如 整数对象 和 浮点对象 都支持加减乘除等 数值型操作, 元组对象 tuple 和 列表对象 list 都支持下标索引操作,
>>> 1 + 2
3
>>> 3.14 * 3.14
9.8596
  • 因此根据对象的行为,将对象进行分类:
    在这里插入图片描述
    (这也是很好的理解了,python中的对象分类!,受益匪浅,大彻大悟~)

  • Python 便以此为依据,为每个类别都定义了一个 标准操作集 :

    • PyNumberMethods 结构体定义了 数值型 操作
    • PySequenceMethods 结构体定义了 序列型 操作;
    • PyMappingMethods 结构体定义了 关联型 操作
  • 只要 类型对象 提供相关 操作集 , 实例对象 便具备对应的 行为!

  • 这里截取书中部分代码,展示例子:

// 以 float 为例,类型对象 PyFloat_Type 相关字段是这样初始化的:
PyTypeObject PyFloat_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "float",
    sizeof(PyFloatObject),

    // ...
    &float_as_number,                           /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */

    // ...
};
  • 解析:
    • 字段 tp_as_number 非空,因此 float 对象 支持数值型操作 ;
    • 字段 tp_as_sequence 为空,因此 float 对象 不支持序列型操作 ;
    • 字段 tp_as_mapping 为空,因此 float 对象 不支持关联型操作 ;
引用计数

原话引入:
在这里插入图片描述
简单的例子(均引用书中例子):

>>> a = 3.14
>>> sys.getrefcount(a)
2
# 这里注意:对象作为函数参数传递,需要将引用计数加一,避免对象被提前销毁;
# 函数返回时,再将引用计数减一。 因此,例子中 getrefcount 函数看到的对象引用计数为 2 !!

# 接着,变量赋值让对象多了一个引用,这很好理解:
>>> b = a
>>> sys.getrefcount(a)
3

# 将对象放在容器对象中,引用计数也增加了,符合预期:
>>> l = [a]
>>> l
[3.14]
>>> sys.getrefcount(a)
4

# 我们将 b 变量删除,引用计数减少了:
>>> del b
>>> sys.getrefcount(a)
3

# 接着,将列表清空,引用计数进一步下降:

>>> l.clear()
>>> sys.getrefcount(a)
2

# 最后,将变量 a 删除后,引用计数降为 0 ,便不复存在了:

>>> del a
  • python中很多场景涉及到 应用计数的调整:
    • 容器操作
    • 变量赋值
    • 函数参数传递
    • 属性操作
  • 为此,Python 定义了两个非常重要的宏,用于维护对象应用计数。 其中, Py_INCREF 将对象应用计数加一 ( 3 行):
#define Py_INCREF(op) (                         \
    _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
    ((PyObject *)(op))->ob_refcnt++)
  • Py_DECREF 将引用计数减一 ( 5 行),并在引用计数为 0 时回收对象 ( 8 行):
#define Py_DECREF(op)                                   \
    do {                                                \
        PyObject *_py_decref_tmp = (PyObject *)(op);    \
        if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
        --(_py_decref_tmp)->ob_refcnt != 0)             \
            _Py_CHECK_REFCNT(_py_decref_tmp)            \
        else                                            \
            _Py_Dealloc(_py_decref_tmp);                \
    } while (0)

最后:(作者话语)
当一个对象引用计数为 0 , Python 便调用对象对应的析构函数销毁对象,但这并不意味着对象内存一定会回收。 为了提高内存分配效率, Python 为一些常用对象维护了内存池, 对象回收后内存进入内存池中,以便下次使用,由此 避免频繁申请、释放内存 。

内存池 技术作为程序开发的高级话题,需要更大的篇幅,放在后续章节中介绍。 让我们期待吧!,我也会持续学习,总结

总结:这一节我们学习了对象的生命周期。知道了如何创建一个对象,实现多态性,以及如何 规定一个对象所具有的行为,以及简单垃圾回收机制,理解对象的销毁。后面会深入的去讲解Python的内置类型,比如list,dict,str等! 期待一起学习,进步!

Spring入门到精通:第二章 IOC容器(XML方式):8.IOC容器Bean管理XML方式-bean的生命周期 生命周期:对象从创建到销毁的过程。 一、bean生命周期 (1)通过构造方法创建bean实例(无参构造方法); (2)为bean的属性设置值和其它bean引用(调用set方法); (3)调用bean的初始化方法(需要进行配置初始化的方法); (4)使用bean(可以获取对象); (5)当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法) 二、演示bean的生命周期 (1)编写类 package com.kfit.test.test7; /** * @au.. 阅读详情

相关推荐

AHB总线协议

1. 简介         AHB总线规范是AMBA总线规范的一部分,AMBA总线规范是ARM公司提出的总线规范,被大多数SoC设计采用,它规定了AHB (Advanced High-performance Bus)、ASB (Advanced System Bus)、APB (Advanced Peripheral Bus)。AHB用于高性能、高时钟频率的系统结构,典型的应用如ARM核与系统内

ivy_reny的专栏 8万+

【Spring】对象的生命周期(创建、初始化、销毁)

文章目录一、生命周期二、创建阶段三、初始化阶段3.1 InitializingBean接口3.2 配置init-method3.3 分析四、销毁阶段4.1 DisposableBean 接口:4.2 配置 destroy-method五、总结 一、生命周期 什么是对象的生命周期? ⼀个对象创建、存活、消亡的⼀个完整过程。 为什么要学习对象的生命周期? 由 Spring 负责对象的创建、存活、销毁,了解生命周期,有利于我们使用好 Spring 为我们创建的对象。 生命周期的 3 个阶段: 创建阶段

See_Star的博客 3148

EastWave应用案例:机箱屏蔽效能仿真

如何使用EastWave对机箱的电磁屏蔽效能进行仿真

2201_76034687的博客 1392

JVM对象从创建到销毁的过程

从创建对象A来谈谈对象的创建到销毁 A a = new A(); 1、用户创建了一个对象A,运行时JVM首先会去方法区寻找该对象的类信息,没有则使用类加载器ClassLoader加载A.class字节码文件 过程:类加载过程 采用双亲委派机制对类进行加载,加载的类信息存放于一块称为方法区的内存空间,除了类信息外,方法区还存放运行时常量池信息 ,常量,静态变量; 分三个阶段 加载: 1 -通过一个类的全限定名获取此类的二进制字节流 2- 将这个字节流文件所代表的静态存储结构转化为 方法...

weixin_47672692的博客 1757

RK3588 EVB开发板原理图讲解【六】

该原理图展示了eMMC Flash与主控芯片之间的连接关系,以及相关的电源、信号线路和去耦电容等。

weixin_48721556的博客 1162

中兴B860AV2.1-A刷机避坑指南:晶晨免拆神器+安卓7.1.2固件实测

本文提供中兴B860AV2.1-A机顶盒的详细刷机教程,重点介绍使用晶晨免拆神器配合安卓7.1.2线刷固件包的实操步骤。内容涵盖刷机前的硬件确认、工具准备、软件设置、烧录全过程监控及常见问题解决,旨在帮助用户安全、高效地完成刷机,规避变砖风险,释放设备潜力。

pytorch8learner的博客 744

Java 对象从创建到毁灭的过程

Step1:类加载检查 虚拟机遇到⼀条 new 指令时,⾸先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引⽤,并且检查这个符号引⽤代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执⾏相应的类加载过程。 加载:获取二进制流,并加载到方法区,并在堆中生成一个java.lang.Class对象,作为方法区这个类的访问入口。 验证:验证字节流是否符合虚拟机的标准 ,比如开头为CA FE BA BE。 准备:为类变量(static)分配内存(注意,逻辑上的方法区,实际上的堆)和零值(初值)。 解

weixin_42042852的博客 1773

STM32F103ZET6驱动57闭环步进电机(连线+代码)

一、设备: 1. STM32F103开发板 (普中F103的板子) 2. 57闭环电机带驱动 3. 24V/3A的直流电源,用于给电机驱动供电 简单说明:使用Keil5编程,主要使用了PWM波,外部中断和时间中断,按键控制电机使能和脱机并且控制PWM的周期,调节周期即调节电机的转速。 二、STM32开发板与电机驱动的连线: 1.PUL-、ENA-、DIR-与STM32的连接方法: 可以参考CSND的这个链接中的说明,使用共阴极接法:STM32F407-用TB6600驱动器驱动57步进电机(代码

baidu_39071234的博客 7428

Java对象的生命周期-内存分配、回收内存

转自:http://www.uml.org.cn/j2ee/201301183.asp Java对象的生命周期     要理解java对象的生命周期,我们需要要明白两个问题, 1、java是怎么分配内存的 ,2、java是怎么回收内存的。 喜欢java的人,往往因为它的内存自动管理机制,不喜欢java的人,往往也是因为它的内存自动管理。我属于前者,这几年的coding经验让我认识到

技术人宝哥 1516

Java 新纪元 — JDK 25 + Spring Boot 4 全栈实战(十九):微服务实战——Boot 4 + Spring Cloud 2026.x,构建高并发电商分布式系统

Component@Slf4j@Autowired// 白名单路径@Override// 白名单放行// 提取Token// 传递用户信息到下游服务.mutate().build();@Override// 最高优先级if (bearer!@Component技术点Boot 3 时代Boot 4 时代提升线程模型平台线程池(200线程上限)虚拟线程(百万级并发)50x+服务通信。

qq_17204557的博客 185

第10章 shellcode实战:18 神级开源shellcode工具:donut

Donut是一款shellcode生成器,可将C/C++、C#生成的PE文件转换为shellcode文件,同时支持JS、XSL、VBS脚本转换为shellcode。以下“原生”EXE/DLL指非托管PE文件(包括并不限于C/C++、delphie等编写生成的可执行文件),可以直接由系统加载运行,区别于.Net生成的托管文件。被处理exe/dll为32位程序,则需要用32为的shellcode加载器启用,exe/dll为64位的就用64位shellcode加载器启用。

李小咖·网安技术库 2794

对象创建过程

这里说的对象创建过程,仅仅指的是普通的对象。创建对象,仅仅只是一个new关键字。 查找是否有符号引用:当虚拟机接收到一个new 指令时,会去常量池里面去找有没有这样到一个符号引用。 是否被加载:判断这个符号引用是否已经被加载链接初始化。如果没有,要先执行类的加载过程。 分配内存:分配内存的时候需要注意线程安全问题,为了避免同一块内存地址被分配给对象的问题。 主要有两种方式来避免 CAS...

ace423839506的专栏 250

记录:解决Ubuntu20.04安装ros报错E: Unable to locate package ros-kinetic-desktop-full【亲测有效】

报错:E: Unable to locate package ros-kinetic-desktop-full.尝试好久一直都无法下载,最后得知真相的我眼泪哗哗的直流。

**My Coding Family** 6万+

创建和销毁对象

本文是Java 四大教科书之一的Effective Java的中文第三版的笔记整理 第二章:创建和销毁对象 1,用静态方法类替代构造器 为什么要使用静态方法而不是public构造器: 优点: 1,静态方法是有名字的,构造器只能根据参数来决定返回实例的类型.但是通过静态工厂方法就可以避开这个过程. 2,可以复用对象,不用每次都创建一个新的实例,而这个实例可以是提前构造好的,从而实现实例受控类. 3,返回原返回类型的任何子类的对象. 4,返回对象的类可以随着每次调用而发生变化,取决于参数值. 5,方法返回的对象

HumphreyHao的博客 463

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

EffectiveJava经验总结:第二章--创建和销毁对象

EffectiveJava经验总结+解释 第一章:使用静态工厂方法代替构造器 本章主要是讲使用静态工厂创造对象要优于构造器创建对象 1、静态工厂方法可以减少创建对象的次数 减少对象创建次数,对于一些长时间使用的对象 例如数据库连接对象,不需要频繁的创建和销毁 整个生命周期一个就够了,将这种类的创建放在静态代码块里面,只创建一个,mysql驱动类创建方式就是这样类似单例模式享元模式 static { try { DriverManager.registerDrive

qq_43546180的博客 293

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Spring的生命周期

Spring 对象的生命周期是指从对象创建到销毁的整个过程,包含了对象的实例化、初始化、使用和销毁等阶段。实例化:当Spring容器接收到创建对象的请求时,它会创建一个对象的实例。属性设置:对象实例化后,Spring 容器会根据配置文件或注解将相关属性设置到对象中。初始化:对象的所有依赖关系都被设置后,Spring容器会调用对象的初始化方法,如定义的init-method。使用:对象初始化完成后,可以被使用于业务逻辑中。销毁。

时间如瑾 代码如诗 1229

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C++性能优化 第二章 C++对象模型

int *pNew = new int[5];  char *pMalloc = (char*)malloc(1); pNew 和pMalloc自身是栈上的内存单元,会被自动释放,而它们指向的内存是堆上的。虽然指向它们的指针已经不存在,但它们不会被自动释放,因此造就了内存泄漏。通过malloc()获得的堆上的内存需要用free()来释放,而通过new获得的堆上的内存,要用delete来释放。

385

《c++程序性能优化》——C++对象模型

第二章 C++对象模型 ~内存区~一般分为以下五个部分1全局/静态变量区2常量数据区3代码区4栈5堆全局变量和静态变量,以及局部的静态变量储存在全局/静态变量区。字符串存储在常量数据区,而且是4个字节对齐的。程序中的其他字符串常量,如printf()中函数中的格式串,也是存储在常量数据区中。通过new和malloc或得的内存是在堆中的内存。堆上分配内存是以16字节对齐的。~全局/静态变量区和常量数据区~全局/静态变量区和常量数据区是程序编译阶段已经分配好的,在整个程序运行的过程中是始终存在的,用于存储全局变

seraphbest的专栏 1084

Effective Java-读书笔记 第二章-创建和销毁对象

更常见的情况是,我们并不确定“缓存项的生命周期是否有意义”,缓存中的项会随着时间的推移变得越来越没有价值,在这种情况下,缓冲应该时不时清除掉没用的项。使用JavaBeans模式,这种方式创建实例很容易,并且易于阅读,但是这有一个严重的缺点:因为构造过程被分到了几个调用中,在构造过程中JavaBeans可能处于不一致的状态,同时JavaBeans模式与不可变类之间存在冲突,这就需要程序员付出额外的努力来确保它的线程安全。公有域方法的优势在于可以清楚的理解这个类是一个Singleton:共有的静态域是静态的。

qq_51732923的博客 206

C++类析构函数调用顺序揭秘:你真的懂对象销毁时的执行流程吗?

掌握C++类析构函数调用顺序,彻底理解对象销毁时的执行流程。适用于继承、组合场景,详解栈对象与堆对象的析构时机及虚析构函数的关键作用。避免资源泄漏,提升程序稳定性,值得收藏。

CodeIsle的博客 620

掌握这4种模式,彻底掌控coroutine_handle的创建与销毁流程

掌握coroutine_handle的创建与销毁流程,解决协程资源泄漏难题。详解4种典型模式,涵盖暂停恢复、异常处理与生命周期管理,提升异步编程效率。深入C++20协程实战技巧,让coroutine_handle 的销毁更安全可控,值得收藏

Algorift的博客 439

【C++析构函数调用顺序深度解析】:掌握类继承与对象销毁的底层逻辑

掌握C++类的析构函数调用顺序,深入解析继承体系中对象销毁的底层机制。涵盖单继承、多继承场景下析构函数执行规则,揭示虚析构函数的关键作用。理解调用顺序可有效避免资源泄漏,提升程序稳定性,值得收藏。

AlgoPerch的博客 1083

【C++ Lambda捕获this的生命周期陷阱】:揭秘对象销毁时的崩溃元凶及避坑指南

深入解析lambda捕获this的生命周期导致的对象销毁崩溃问题,揭示C++中常见陷阱及安全捕获方法。涵盖成员函数内lambda使用场景、引用捕获风险与解决方案,助你写出稳定代码。避坑指南值得收藏

QuickProceed的博客 452

C++对象销毁顺序全梳理:从栈对象到全局对象,析构函数调用顺序一文讲透

掌握析构函数的调用顺序,彻底理清C++对象销毁机制。从栈对象、堆对象到全局对象,详解各类对象析构时机与执行顺序,助你避免资源泄漏。涵盖构造与析构匹配原则、局部与静态对象行为差异,深入浅出,值得收藏。

FastSolve的博客 494

C++析构函数何时被调用:深入理解继承、组合与栈对象的销毁顺序

掌握C++析构函数的调用顺序,深入解析继承与组合中对象销毁的执行逻辑。涵盖栈对象、基类派生类析构顺序及资源管理要点,帮助开发者避免内存泄漏。理解机制背后的核心规则,值得收藏。

FuncFun的博客 1012

【C++11线程安全核心】:为什么你的 thread_local 对象在main后才销毁?

深入解析C++11 thread_local 的销毁机制,揭示对象为何在main函数结束后才释放。涵盖线程局部存储的生命周期管理、析构顺序及多线程场景下的安全实践,避免资源泄漏。掌握这一机制的关键细节,提升程序稳定性,值得收藏。

CodeVibe的博客 300
上一篇: 第二章对象模型(2):揭开对象的神秘面纱
下一篇: 完整电商项目--项目介绍(1)
我是py呀
博客等级 码龄8年 205粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值