折腾打印

  • 让list打印时顺便输出索引
  • 改变dict键值位置

让list打印时顺便输出索引

首先,作为基本素质,请先备份源码免得搞坏了又要下载.其次,方便自己,把玩过的东西改回去,免得自己把自己绕着了(比如应该是True的你给我打印一个False我可记不清楚呢)

定位到static PyObject *list_repr(PyListObject *v)函数(记住了,_repr后缀应该就是负责打印的,以后都对这种函数下手就完了)
位于Objects/listobject.c:361,贴出来函数体吧

Py_ssize_t i;
PyObject *s;
_PyUnicodeWriter writer;if (Py_SIZE(v) == 0) {return PyUnicode_FromString("[]");
}i = Py_ReprEnter((PyObject*)v);
if (i != 0) {return i > 0 ? PyUnicode_FromString("[...]") : NULL;
}_PyUnicodeWriter_Init(&writer);
writer.overallocate = 1;
/* "[" + "1" + ", 2" * (len - 1) + "]" */
writer.min_length = 1 + 1 + (2 + 1) * (Py_SIZE(v) - 1) + 1;if (_PyUnicodeWriter_WriteChar(&writer, '[') < 0)goto error;/* Do repr() on each element.  Note that this may mutate the list,so must refetch the list size on each iteration. */
for (i = 0; i < Py_SIZE(v); ++i) {if (i > 0) {if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)goto error;}s = PyObject_Repr(v->ob_item[i]);if (s == NULL)goto error;if (_PyUnicodeWriter_WriteStr(&writer, s) < 0) {Py_DECREF(s);goto error;}Py_DECREF(s);
}writer.overallocate = 0;
if (_PyUnicodeWriter_WriteChar(&writer, ']') < 0)goto error;Py_ReprLeave((PyObject *)v);
return _PyUnicodeWriter_Finish(&writer);error:
_PyUnicodeWriter_Dealloc(&writer);
Py_ReprLeave((PyObject *)v);
return NULL;

然后勉强能阅读这些代码,就是先输出一个"[",然后根据情况遍历整个列表,分别调用其repr函数(这个有些特殊,内部机制实际上是函数指针),然后循环下一个,直到最后一个就输出一个"]".特别好理解.下面来搞事情.
我们先来试试输出值和它的索引,热热身.
在for外部声明一个局部变量.char *tmp_s = malloc(100);,并分配空间;
然后在每次循环的时候格式化一下索引并修改输出函数的参数,让他打印tmp_s;
最后一个对象,特殊处理就完啦~
代码如下:Objects/listobject.c:385-413

char *tmp_s = (char*)malloc(100);
/* Do repr() on each element.  Note that this may mutate the list,so must refetch the list size on each iteration. */
for (i = 0; i < Py_SIZE(v); ++i) {sprintf(tmp_s, " : %d, ", i);if (i > 0) {//if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)if (_PyUnicodeWriter_WriteASCIIString(&writer, tmp_s, strlen(tmp_s)))goto error;}s = PyObject_Repr(v->ob_item[i]);if (s == NULL)goto error;if (_PyUnicodeWriter_WriteStr(&writer, s) < 0) {Py_DECREF(s);goto error;}Py_DECREF(s);
}writer.overallocate = 0;
// i的值未改变,还是最后一个索引值
//if (_PyUnicodeWriter_WriteChar(&writer, ']') < 0)
// 需要调用输出字符串的函数!
sprintf(tmp_s, " : %d]", i);
if (_PyUnicodeWriter_WriteASCIIString(&writer, tmp_s, strlen(tmp_s)) < 0)goto error;

运行效果:

实现了预期效果,但…这个索引从1开始很离谱,我们修改一下:
把L389和L411的sprintf第三个参数改成i-1.

好,既然如此,那我们给他搞个大事情:全给我倒着输出!
(偷偷删掉刚刚的恶作剧)
实现原理:修改v->ob_item的索引,改成"数组大小-前索引-1",就是反着遍历啦

运行,正常:

突发奇想,如果嵌套列表会怎么样?肯定都反过来,下图为证:

改变dict键值位置

折腾玩list,怎么能放过dict?!
定位static PyObject *dict_repr(PyDictObject *mp)@Objects/dictobject.c:2093(足够后面…幸好有搜索功能)

简单起见哈,我们仅仅改变key和value的值(这足够过分了,当你的朋友看见不可哈希对象(比如list)出现在键的位置,咱可以想象一下那表情[])

首先找到L2123循环开始,其他的可以简单浏览下,都能看懂的相信.仅仅讲一下很重要的两个宏(每个源码解析书都会说到,我自然不能落后对不对)Py_INCREFPy_DECREF

跟着vs的访问,找到这个宏一步步展开的最终结果:(以INCREF为例)
object.h:475->object.h:461(函数),手动找到实现,结果无能为力啊…那就直接说吧
分词:INC(increase) REF(reference) 增加引用(计数)
众所周知每个PyObject结构体都有个引用计数,这根gc(垃圾回收)紧密相连,python虚拟机的垃圾回收机制可以肤浅的理解成,维护每个对象的引用计数器,每次引用变量就自增1,当那个引用的变量被del(析构,或删除)后,自减1,gc要做的事就是在引用计数变成0的时候发现,并干掉这个没用的垃圾

当然,这么复杂的解释器内部肯定不只说的这么简单,它需要考虑是事情更多,优化也很重要,勉强这么理解就行了.

下面正式向dict进攻:

熟练地恶作剧技巧告诉我们,这个repr字眼肯定是打印用的,事实也正是如此,我深入看过它的实现,特别复杂,函数调用有接近十层(真没吹)

这里也顺便引出阅读大型项目源码的一大难点:他为了全局上的方便,牺牲局部的可读性.什么意思呢?就是说,你一个不是它项目组的人去看,多半看不大懂,因为你脑子里没有开发者脑子里的结构图,你不知道哪个函数是哪个逻辑层(我喜欢这么称呼),也不清楚它会调用到哪里去,或者被谁调用.源码阅读者若不是修养特别深,多半脑海里都仅仅是一个个散着的函数(本人自己写过中型项目,我可以清晰说出我项目里的层次而你看半天估计也看不明白),因此这里我就把关键的调用节点都给大家调查好,毕竟vs操作不那么方便(或者我不熟练,我喜欢vscode)

回归正题,为了实现目标(改变键值位置),关注到英文单词valuekey出现的位置,如截图,在L2137和L2148位置,试着调换他们应该就行.如下:

(还是那句话,记得改回来哦)

单凭那个[123, 234]:'abc'就足够吓懂python的朋友一跳了哈哈哈
(还有那个集合作为键,真的特别反人类),ok,dict的倒腾成功!

关于如何搭建环境,请看上一章
玩腻了输出的把戏,下一章我们来盘一下运行时~链接

2-折腾python:继续一些瞎打印的小把戏相关推荐

  1. python画图代码星星-Python利用for循环打印星号三角形的案例

    简单的for循环打印三角形 1,for循环方法实现星星三角 代码: for i in range(0,5): for j in range(i+1): if i == 4: print("* ...

  2. python tqdm进度条打印

    python tqdm进度条打印 使用tqdm来进行迭代可以打印进度条,tqdm中的tqdm()是实现进度条美化的基本方法,在for循环体中用tqdm()包裹指定的迭代器或range(). 简单展示: ...

  3. python打印表格_怎么使用python脚本实现表格打印?

    大家在办公学习中,有没有被打印机的功能所惊叹?可能大部分小伙伴并没有在意打印机的实现原理,只知道它是可以复印东西的,当小编提出这个问题的时候,那大家有没有考虑过呢?有些小伙伴可能会说这个和我们Pyth ...

  4. Python使用for循环打印金字塔

    文章目录 1. 正金字塔 2. 倒金字塔 3. 数字金字塔 1. 正金字塔 # 打印形状 #**************** *********# 实现代码 # # 将金字塔看作一个由左边矩形.右边三 ...

  5. python中怎么打印出表格_怎么使用python脚本实现表格打印?

    大家在办公学习中,有没有被打印机的功能所惊叹?可能大部分小伙伴并没有在意打印机的实现原理,只知道它是可以复印东西的,当小编提出这个问题的时候,那大家有没有考虑过呢?有些小伙伴可能会说这个和我们Pyth ...

  6. python在cmd中打印彩色文字

    版权声明:此文首发于我的个人站python在cmd中打印彩色文字,转载请注明出处. 百度来的 颜色值不太准确,下面的是亲测修改的: 单独写了一个文件 printColor.py,使用的时候只要作为模块 ...

  7. python中for循环打印菱形_Python 使用双重循环打印图形菱形操作

    如下所示: a = int(input("请输入菱形行数:")) m = a #空格 d = a #倒三角 for i in range(1, a + 1): # 先打印正三角 p ...

  8. python皮卡丘字符打印代码,python画皮卡丘的代码

    大家好,本文将围绕用python画一只可爱的皮卡丘展开说明,python皮卡丘字符打印代码是一个很多人都想弄明白的事情,想搞清楚python皮卡丘编程代码教程需要先了解以下几个事情. 1.python ...

  9. 关于Python控制打印机如何横向打印EXEL

    关于Python控制打印机如何横向打印EXEL 在python的使用中,经常在开发的时候会遇到要多个模块联合使用的问题.在一次项目中我就遇到一个这样的问题. 在项目中,要求实现存数据到exel.然后控 ...

  10. python怎么操作打印机打印文字

    python怎么操作打印机打印文字 import tempfile import win32api import win32printfilename = tempfile.mktemp (" ...

最新文章

  1. 基于 TensorFlow 的图像识别(R实现)
  2. 在一个空的Eclipse中安装Android开发的ADT和SDK
  3. 神策数据联合Ping++,推出电商、O2O 行业的 GMV 增长研讨
  4. java 将查询到的值 存下_MyBatis3.x 从入门到精通(六)查询
  5. 放下表格——开箱即用的新冠疫苗接种统计模板来了!
  6. 华为 命令 so easy
  7. 在网上找到一个CSS hack列表,记录在这里以分析css的浏览器兼容性
  8. 信息学奥赛一本通(1163:阿克曼(Ackmann)函数)
  9. python项目上线_django之项目部署上线
  10. 人造电子皮肤、软体机器人、单孔腔镜手术机器人......青年科学家们都在研究哪些“黑科技”?...
  11. 跨浏览器resize事件分析
  12. java 汇率换算_原生JS实现简单的汇率转换问题
  13. dispatch_apply快速迭代
  14. cidaemon.exe过程cpu入住率和关闭cidaemon.exe加工方法
  15. CTF-网络信息安全攻防学习平台(脚本关)
  16. word自动消除html标签,如何将Word转换为网页html格式的方法(附代码清理方法)
  17. php复姓怎么排序,怎样“按姓氏笔画排列”? 复姓和少数民族姓氏如何排列? 男女同名谁在前...
  18. 中科深谷开源智能两轮平衡车
  19. javascript replace将文字表情替换为图片 (实用、赞)
  20. 非官方谷歌地图 iOS 应用遭苹果下架

热门文章

  1. 回程路由 的作用 为什么 什么时候需要回程路由
  2. 网络安全——WEP实现无线局域网安全
  3. 符合 V.25TER 的 AT 命令
  4. 直播美颜SDK从技术层面如何自行实现
  5. Odoo owl 学习笔记之13—event_handing
  6. 【壁上观】AMD ZEN将至能战8核i7 Intel慌不慌?
  7. 全网最细海龟 (turtle) 画图讲解 (三):设置画笔样式
  8. 将进酒计算机应用技术学院信息门户,《将进酒》信息化教学设计
  9. 企信下载的文件在哪里_iTunes下载的固件在哪 iTunes固件下载地址【介绍】
  10. HHKB静电容键盘真是程序员键盘吗?