第三章内建对象(1):小试牛刀,解剖浮点对象 float

float_add.v verilog实现浮点数加法运算,采用单精度浮点型格式,实现硬件浮点数相减,并且可以根据需要更改其浮点型减法的精度 立即下载

前言:后续小结将会陆续介绍python内建对象我们将从对象模型中挑出 float 先讲解,因为它是 Python 中最简单的对象之一,“麻雀虽小,五脏俱全”, 拥有对象的全部必要属性!
  • 以 float 对象为起点开启源码之旅,能够快速上手,为研究更复杂的内置对象打好基础,建立信心!
(1)内部结构
  • float 实例对象在 Include/floatobject.h 中定义
// 结构很简单,和上几节了解的一样
typedef struct {
    PyObject_HEAD
    double ob_fval;
} PyFloatObject;

定长对象共用的头部,只有一个额外的字段 ob_fval ,存储对象所承载的浮点值。

  • 内置类型float对象,与实例对象不同的点是:float 类型对象 全局唯一 ,因此可以作为 全局变量 定义。
// 在 C 文件 Objects/floatobject.c 中,我们找到了代表 float 类型对象的全局变量 PyFloat_Type 
PyTypeObject PyFloat_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "float",
    sizeof(PyFloatObject),
    0,
    (destructor)float_dealloc,                  /* tp_dealloc */
    0,                                          /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_reserved */
    (reprfunc)float_repr,                       /* tp_repr */
    &float_as_number,                           /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)float_hash,                       /* tp_hash */
    0,                                          /* tp_call */
    (reprfunc)float_repr,                       /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */
    float_new__doc__,                           /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    float_richcompare,                          /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    float_methods,                              /* tp_methods */
    0,                                          /* tp_members */
    float_getset,                               /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    float_new,                                  /* tp_new */
};

内容很长!

  • PyFloat_Type 中保存了很多关于浮点对象的 元信息(元数据) ,关键字段包括:

    • tp_name 字段保存类型名称,常量 float
    • tp_dealloc 、 tp_init 、 tp_alloc 和 tp_new 字段是对象创建销毁相关函数;
    • tp_repr 字段是生成语法字符串表示形式的函数;
    • tp_str 字段是生成普通字符串表示形式的函数;
    • tp_as_number 字段是数值操作集;
    • tp_hash 字段是哈希值生成函数;
  • PyFloat_Type 很重要,作为浮点 类型对象 ,它决定了浮点 实例对象 的 生死和行为 。 接下来,我们以不同小节分别展开讨论

对象的创建:
  • 调用类型对象 float 创建实例对象,Python 执行的是 type 类型对象中的 tp_call 函数。 tp_call 函数进而调用 float 类型对象的 tp_new 函数创建实例对象, 再调用 tp_init 函数对其进行初始化:图片理解 参考上一节中的例子

  • 除了通用的流程, Python 为内置对象实现了对象创建 API ,简化调用,提高效率

PyObject *
PyFloat_FromDouble(double fval);

PyObject *
PyFloat_FromString(PyObject *v);

// PyFloat_FromDouble 函数通过浮点值创建浮点对象;
// PyFloat_FromString 函数通过字符串对象创建浮点对象

这解释了,不管传入 浮点值,还是字符串,float()都可以创建浮点实例对象。

  • 以 PyFloat_FromDouble 为例,特化的对象创建流程如下:
PyObject *
PyFloat_FromDouble(double fval)
{
    PyFloatObject *op = free_list;
    if (op != NULL) {
        free_list = (PyFloatObject *) Py_TYPE(op);
        numfree--;
    } else {
        op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject));
        if (!op)
            return PyErr_NoMemory();
    }
    /* Inline PyObject_New */
    (void)PyObject_INIT(op, &PyFloat_Type);
    op->ob_fval = fval;
    return (PyObject *) op;
}

// 为对象 分配内存空间 ,优先使用空闲对象缓存池 (第 4-12 行);
// 初始化 对象类型 字段 ob_type 以及 引用计数 字段 ob_refcnt (第 14 行);
// 将 ob_fval 字段初始化为指定 浮点值 (第 15 行);
  • 其中宏PyObject_INIT 在头文件 Include/objimpl.h 中定义:
#define PyObject_INIT(op, typeobj) \
    ( Py_TYPE(op) = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
  • 宏 _Py_NewReference 将对象引用计数初始化为 1 ,在 Include/Object.h 中定义:
#define _Py_NewReference(op) (                          \
    _Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA         \
    _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA               \
    Py_REFCNT(op) = 1)

对象的销毁

  • 注意:当对象不再需要时, Python 通过 Py_DECREF 或者 Py_XDECREF 宏减少引用计数; 当引用计数降为 0 时, Python 通过 _Py_Dealloc 宏回收对象。
  • 而 _Py_Dealloc 宏调用类型对象 PyFloat_Type 中的 tp_dealloc 函数指针
#define _Py_Dealloc(op) (                               \
    _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA          \
    (*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))
下面总结,对象从创建到销毁整个生命周期所涉及的 关键函数、宏及调用关系 如下,非常清晰!

在这里插入图片描述

这些都相当于是对上一节中 对浮点类型举例的扩展与细致总结。

空闲对象缓存池: 解决频繁的对象创建及销毁时的效率问题(提高对象分配效率)

  • 浮点运算背后涉及 大量临时对象创建以及销毁 ,以计算圆周率为例
>>> area = pi * r ** 2
    • (1)首先计算半径 r 的平方,中间结果由一个临时对象来保存,假设是 t
    • (2) 接着计算圆周率 pi 与 t 的乘积,得到最终结果并赋值给变量 area
    • (3)销毁临时对象t
  • 显然:创建对象时需要分配内存,销毁对象时又需要回收内存。 大量临时对象创建销毁 ,意味着 大量内存分配回收操作,这是非常牺牲效率的!

  • 改善: Python 在浮点对象销毁后,并不急于回收内存,而是将对象放入一个 空闲链表!!,后续需要创建浮点对象时,先到空闲链表中取,省去分配内存的开销。

  • 浮点对象的空闲链表同样在 Objects/floatobject.c 中定义:

#ifndef PyFloat_MAXFREELIST
#define PyFloat_MAXFREELIST    100
#endif
static int numfree = 0;
static PyFloatObject *free_list = NULL;
    • free_list 变量,指向空闲链表 头节点 的指针

    • numfree 变量,维护空闲链表 当前长度

    • PyFloat_MAXFREELIST 宏,限制空闲链表的 最大长度 ,避免占用过多内存

(这里是我没有读懂的地方,ob_type作为 next指针)
在这里插入图片描述

  • 由此一来,需要创建浮点对象时,可以从链表中取出空闲对象,省去申请内存的开销! 以 PyFloat_FromDouble 为例:
PyFloatObject *op = free_list;
if (op != NULL) {
    free_list = (PyFloatObject *) Py_TYPE(op);
    numfree--;
} else {
    op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject));
    // ...
}
    • (1)检查 free_list 是否为空(第 2 行);
    • (2)如果 free_list 非空,取出头节点备用, 并将 numfree 减一(第 3-4 行)
    • (3)如果 free_list 为空,则调用 PyObject_MALLOC 分配内存(第 6 行);

作者温馨的提示:如果对 C 语言链表操作不熟悉,可以结合以下图示加以理解:
在这里插入图片描述

  • 对象销毁时, Python 将其缓存在空闲链表中,以备后用。考察 float_dealloc 函数:
if (numfree >= PyFloat_MAXFREELIST)  {
    PyObject_FREE(op);
    return;
}
numfree++;
Py_TYPE(op) = (struct _typeobject *)free_list;
free_list = op;
    • 第 1-4 行,空闲链表长度达到限制值,调用 PyObject_FREE 回收对象内存;
    • 第 5-7 行,空闲链表长度暂未达到限制,将对象插到空闲链表头部;
这就是 Python 空闲对象缓存池的全部秘密! 由于空闲对象缓存池在 提高对象分配效率 方面发挥着至关重要的作用, 后续研究其他内置对象时,我们还会经常看到它的身影

对象的行为

  • 举个例子:例如 tp_hash 函数决定浮点哈希值的计算
>>> pi = 3.14
>>> hash(pi)
322818021289917443

tp_hash 函数指针指向 float_hash 函数,实现了针对浮点对象的哈希值算法:

static Py_hash_t
float_hash(PyFloatObject *v)
{
    return _Py_HashDouble(v->ob_fval);
}
数值操作集
  • 上节中提到了,对于共性的操作,python将其抽象为 操作集。
  • 回到 Objects/floatobject.c 观察浮点对象数值操作集 float_as_number 是如何初始化的:
static PyNumberMethods float_as_number = {
    float_add,          /* nb_add */
    float_sub,          /* nb_subtract */
    float_mul,          /* nb_multiply */
    float_rem,          /* nb_remainder */
    float_divmod,       /* nb_divmod */
    float_pow,          /* nb_power */
    (unaryfunc)float_neg, /* nb_negative */
    // ...

    0,                  /* nb_inplace_add */
    0,                  /* nb_inplace_subtract */
    0,                  /* nb_inplace_multiply */
    0,                  /* nb_inplace_remainder */
    0,                  /* nb_inplace_power */
    // ...
};
  • 以加法为例,以下语句在 Python 内部最终由 float_add 函数执行:
>>> a = 1.5
>>> b = 1.1
>>> a + b
2.6
  • float_add 是一个 二元函数 ,同样位于 Objects/floatobject.h 中:
static PyObject *
float_add(PyObject *v, PyObject *w)
{
    double a,b;
    CONVERT_TO_DOUBLE(v, a);
    CONVERT_TO_DOUBLE(w, b);
    PyFPE_START_PROTECT("add", return 0)
    a = a + b;
    PyFPE_END_PROTECT(a)
    return PyFloat_FromDouble(a);
}
    • 函数实现只有寥寥几步
      • 首先 将两个参数对象转化成浮点值( 5-6 行);
      • 然后 对两个浮点值求和( 8 行);
      • 最后,创建一个新浮点对象保存计算结果并返回( 10 行)

这就是浮点类型的内容。大部分都是在上节中所讲到的内容! 我们巩固和加深理解。

下一节:讲解两个面试题

SAR成像系列:【3】合成孔径雷达(SAR)的二维回波信号与简单距离多普勒(RD)算法 (附matlab代码) 二维回波信号分析 阅读详情

相关推荐

Zipformer实战:5分钟快速搭建语音识别模型(附LibriSpeech测试结果)

本文提供了一份详细的Zipformer语音识别模型实战指南。通过清晰的步骤,指导读者在5分钟内完成从环境配置、LibriSpeech数据集准备到模型训练与测试的全过程。文章重点解析了关键配置参数,并分享了在LibriSpeech测试集上的性能结果,帮助开发者快速评估和应用这一高效的语音识别架构。

weixin_35578748的博客 159

第三章内建对象(2):浮点对象----面试题讲解

1

pythonstrat的博客 247

DBeaver连接IoTDB避坑指南:手动配置JDBC驱动的完整流程(附问题排查)

本文提供了在DBeaver中手动配置Apache IoTDB JDBC驱动的完整流程与避坑指南。详细解析了从驱动创建、库文件添加(关键是指向整个lib目录)到连接测试的每一步,并重点针对常见的ClassNotFoundException、连接拒绝等错误提供了深度排查方案,帮助用户高效建立图形化管理连接。

weixin_28327051的博客 393

2. Python3源码—浮点对象

2.1. 浮点对象 浮点对象是“定长对象”。 2.1.1. Python中的创建 Python中浮点对象创建最重要的方法为PyFloat_FromDouble,如下Python语句最终会调用到PyFloat_FromDouble: a = 1.23 b = float(1.234) 2.1.2. PyFloat_FromDouble的C调用栈 词法解析,...

weixin_34315189的博客 299

HALCON实战:用两个工业相机实现无缝大视野拼接(附完整代码与避坑指南)

本文详细介绍了使用HALCON软件实现双工业相机图像无缝拼接的完整解决方案,涵盖硬件配置、相机标定、坐标系转换和图像拼接等关键步骤。通过高精度标定和矩阵变换技术,可构建大视野检测系统,适用于液晶面板、PCB等工业检测场景,显著提升检测效率和精度。

weixin_29050513的博客 190

Cadence 17.2 OrCAD原理图库实战:从零创建电阻/电容/LED元件(附封装技巧)

本文以Cadence 17.2 OrCAD为核心,详细讲解了如何从零开始工程化地创建电阻、电容、LED等原理图库元件。内容涵盖库架构设计、符号绘制、引脚属性管理、封装关联技巧以及设计规则检查,旨在帮助硬件工程师构建规范、可复用且易于维护的元件库,为高效PCB设计奠定坚实基础。

weixin_29195615的博客 399

python 多态的实现_PyObject多态的实现

PyObject的多态实现PyObject 是 Python 所有对象的基石,所有其他对象 PyIntObject 和 PyFloatObject 的行为,当强制转换为 PyObject 时,都可以正确得到结果。这就很类似于面向对象的多态。而 CPython 是 C 语言的,并没有面向对象的概念。所以本文就从 CPython 的源码,简单分析下 PyObject 多态的实现原理1. PyObjec...

weixin_39690625的博客 318

【ros2】ros2_control 全面解析与实战指南

ros2_control 是 ROS2 生态中用于机器人实时控制的核心框架,旨在统一硬件接入接口、复用控制算法,避免重复开发,实现仿真与实机硬件的无缝迁移。其核心目标是简化不同硬件(传感器、执行器、完整系统)的集成流程,让开发者专注于控制逻辑而非硬件适配。创建类型功能包,依赖rclcpp。实现on_initupdate在中声明控制器插件,编译生成动态库。在 YAML 配置文件中指定自定义控制器类型,加载测试。

EnHengNa的博客 1467

c语言 垃圾回收,C语言源码分析垃圾回收机制

两个重要的结构体#define PyObject_HEAD PyObject ob_base;#define PyObject_VAR_HEAD PyVarObject ob_base;// 宏定义,包含 上一个、下一个,用于构造双向链表用。(放到refchain链表中时,要用到)#define _PyObject_HEAD_EXTRA \struct ...

weixin_30695909的博客 732

Android 15.0 添加自定义服务,并生成jar给第三方app调用

在15.0系统ROM产品定制化开发中,由于需要新增加自定义的功能,所以要增加自定义服务,而app上层通过调用自定义服务,来调用相应的功能,所以系统需要先生成jar,然后生成jar 给上层app调用,接下来就来分析实现的步骤,然后来实现相关的功能 从而来实现所需要的功能

安卓兼职framework和app工程师的博客 667

AI Agent Harness实时监控大屏搭建实战

本文将以目前主流的AI Agent管控框架Harness为基础,结合React、ECharts、WebSocket技术,手把手带你搭建一套完整的实时监控大屏,覆盖全局概览、状态分布、工具调用统计、异常告警、实时日志等核心功能,不需要复杂的底层开发,复制代码就能快速跑通。本文我们从需求出发,先梳理了AI Agent的核心监控指标,然后搭建了监控大屏的静态布局,逐个实现了各个图表,对接了Harness的实时数据源,最后加了交互和告警功能,完整走了一遍监控大屏从设计到落地的全流程。

大数据洞察的博客 170

ViT在CIFAR-10上训练失败的三大幻觉与实操生存指南

Vision Transformer(ViT)是一种将图像分块建模为序列的视觉骨干网络,其核心原理依赖patch embedding、可学习位置编码和LayerNorm稳定训练。不同于CNN的局部归纳偏置,ViT需在小数据集如CIFAR-10上重新设计优化策略——AdamW优化器、linear warmup调度、DropPath正则化及patch_size=16的精度-效率平衡点,共同构成ViT稳定收敛的技术价值。典型应用场景包括轻量级图像分类、教学实验与模型鲁棒性验证,而本文聚焦于破解ViT在CIFAR-

weixin_33805743的博客 455

在RV1126上实现人脸识别----MobileFaceNet转成rknn模型

目录 1.模型下载 2 转成rknn模型并推理 3 查看网络模型 1.模型下载 首先下载MobileFaceNet的模型,github下载地址为:https://github.com/sirius-ai/MobileFaceNet_TF/tree/master/arch/pretrained_model/ 2 转成rknn模型并推理 import numpy as np import cv2 from rknn.api import RKNN if __name__ == '__..

C/C++、嵌入式开发、深度学习算法、模型部署与推理优化 3525

Python学习14:内置函数(二)

笔者原创,文章转载需注明,如果喜欢请点赞+关注,感谢支持!本文为Python函数学习系列第三篇,python的常用内置函数。 由于篇幅问题,目前官网基于python3.7.7一共包含69个内置函数,共分为3个章节进行讲解,每个章节包含23个内置函数,同时会重点讲解常用的的内置函数。本文为第二章节, python官网关于内置函数的说明:https://docs.python.org/zh-cn/3.7/library/functions.html Python常用的内置函数 上一篇内置...

风起怨江南 564

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Float Sum(浮点数的加法)

#include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFSIZE 256 int main(int argc, char *argv[]) { char prefix[BUFSIZE]; char next[BUFSIZE]; int i; floa...

weixin_44688476的博客 4868

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

浮点数float累加误差解决方式总结

首先是float累加产生误差的原因,该部分转自:http://blog.youkuaiyun.com/zhrh0096/article/details/38589067 1.  浮点数IEEE 754表示方法 要搞清楚float累加为什么会产生误差,必须先大致理解float在机器里怎么存储的,具体的表示参考[1] 和 [2], 这里只介绍一下组成 由上图可知(摘在[2]), 浮点数由:

wolf96的专栏 2万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Float IP 浮动IP地址

就是主机工作方式 是集群,即两台主机以上。每台机器除了自己的实IP外,会设置一个浮动IP,浮动IP跟着机器的服务绑在一起的。即应用服务在哪台机器上启动,浮动IP也在这台机器上激活,这台机器就有两个IP地址。对于客户端它只需访问浮动IP即可。 即使主机端的机器发生切换,客户端只要连接上浮动IP,就可以找到主机端的服务

wjw7869的专栏 1万+

第二章对象模型(1)

对象模型的概述 首先我们要始终铭记一句话:python是一门面向对象的语言! 并且面向的彻底,可以称为 一切皆对象。 这句话说起来简单,如要真正的让你论述其正确性,这就需要很深的功底去理解。 列举常见的对象 1. 例如我们常讲的类 ,它就是 对象。类的细致描述就是类型,再细致解释说就是类型对象,比如:a = 3 # a 是 int类型 b = 'hello' # b 是字符串类型 接着 我们通过class 关键字定义的类,也称为自定义类型对象 通过类(类型对象)实例化得到的实例化对象 >

pythonstrat的博客 2198

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

1. 对象的创建 首先我们需要观察思考: Python 内部是如何从无到有创建一个浮点对象的 Python 又是怎么知道该如何将它打印到屏幕上的呢? >>> pi = 3.14 >>> print(pi) 3.14 下面以 floatl类型为例子,对应C实体是 PyFloat_Type 首先来介绍C API Python 是用 C 写成的,对外提供了 C API ,让用户可以从 C 环境中与其交互。 Python 内部也大量使用这些 API ,为了更好研

pythonstrat的博客 624

Python字典hash表的模拟实现

本文学习自:《Python 源码深度剖析》 感谢作者的传授 若还不清楚字典的知识, 详细内容和知识点可点击了解 功能 主类(字典):PyDictObject (1) add_entry(self, key, value) : 添加元素 (2)del_entry(self, key) : 删除元素 (3) hash_list : (属性),可以遍历底层hash数组 (4) entry_list: (属性),遍历底层键值对数组 (5) 可通过简单的 for循环迭代,很方便 pd = PyDictOb

pythonstrat的博客 618

Python中 a, b = b, a 的具体字节码实现? 以及会出现的问题!

首先引入问题: 力扣448题: 这是我的一种解法: class Solution: def findDisappearedNumbers(self, nums): rst = list() # 循环遍历每一个数组元素 for i in range(len(nums)): # 判断该元素位置上的值,是否需要交换, 注意 循环条件 while nums[i] != i + 1 and nums[i] !

pythonstrat的博客 473

第二章对象模型(2):揭开对象的神秘面纱

前言:上一节中提到了很多的基本概念,是在python层面进行 描述的,总体概念。现在我们就具体了解下 python源码,基于C语言 概念复习 复习一下和要清楚的前面讲的基本概念: 面向对象理论中**“ 类** ”和**“ 对象 ”这两个重要概念,在 Python 内部均以对象**的形式存在。 “类”是一种对象,称为 类型对象 ;“类”实例化生成的“对象”也是对象,称为 实例对象。 根据上文描述的,根据对象的不同特点还可以进行分类: 可变对象: 对象创建后可以修改 不可变对象: 对象创建后不能修改 定长对象:

pythonstrat的博客 399

小整数静态对象池相关问题

上问题 整数对象是 不可变对象 ,整数运算结果是以 新对象 返回的,但是: >>> a = 1 + 0 >>> b = 1 * 1 >>> id(a), id(b) (4408209536, 4408209536) >>> c = 1000 + 0 >>> d = 1000 * 1 >>> id(c), id(d) (4410298224, 4410298160) python 小整数池里 默

pythonstrat的博客 282

Python+Agent入门笔记(二):列表推导式、模块和异常,这些写 Agent 前得会

接上一篇《Python+Agent入门笔记(一)》。基础语法跑通之后,这篇聊几块日常写脚本绕不开的东西。还是按 JS/Go 开发者的视角写,尽量记录我实际卡过的地方。

qq_41241612的博客 428

微调数据集构建:清洗、标注、格式转换完整流程

摘要解决微调数据直接抓取导致的噪声污染、模式崩溃与Token错位问题。适用于需为大模型SFT阶段构建高质量训练集的数据与算法工程师。读完可获得包含启发式清洗、MinHash去重及ChatML格式对齐的完整可运行数据流水线。关键词数据清洗、MinHash去重、数据标注、ChatML、SFT数据集、数据配比背景与问题大模型微调效果的上限由数据质量决定,直接使用未经处理的原始语料极易引发模型复读、幻觉与指令遵循能力退化。

2402_85729970的博客 468
上一篇: 完整电商项目--django项目配置(5):日志文件的简单配置
下一篇: 第三章内建对象(2):浮点对象----面试题讲解
我是py呀
博客等级 码龄8年 205粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值