Skip to main content

这样理解 Python 闭包

· 2 min read
Alex Chen
The main character of the story

看了 12 步轻松搞定 python 装饰器 里的描述后,对『closure 是上下文』有了些形象的理解,一些应用了 closure 的实践可以参考文章里的一些例子,例如函数参数定制生成,装饰器功能等


g_var = 20

def outer():
loc_var = 30
def inner():
print('I can access g_var: %s, loc_var: %s' % (g_var, loc_var))
return inner

in_fun = outer()

# 内层使用到的[外层函数的本地变量]会加入到 func 对象的 __closure__ tuple 里面
print(in_fun.__closure__)

# 全局变量不包含在 closure tuple,并不是副本
g_var = 5000

# 效果就是 in_fun 本身函数内的代码,加上 __closure__ 里的上下文副本实现了 closure 功能
in_fun()

# 也就是说 __closure__ tuple 包含一个 cell 元素,cell 装有外层的 loc_var,值是 30
print('There is %d cell inside' % len(in_fun.__closure__))
print('This cell contain %d' % in_fun.__closure__[0].cell_contents)


shellman 一个 Linux 堆溢出利用例题的分析

· 8 min read
Alex Chen
The main character of the story

ALARM signal 自动退出程序

首先把玩一下,发现有个 alarm 事件令程序在一分钟后退出,这里在二进制修改一下时间值去掉这个小玩意,并不会影响后续堆溢出的分析。

时间值在 main 函数上作为立即数传给 alarm,用 IDA 或别的反汇编工具可以看到 一时间没有好用的二进制编辑,发现用 vi 也非常方便 https://www.zhihu.com/question/22281280/answer/34778466

ALARM signal 时长

之后的动态分析会用这个修改过的 shellman_noalarm 就不会一分钟后退出,看了网上一些介绍 gdb 可以屏蔽 ALARM signal, 也是可行方法吧。

理解 TCP 的三次握手、四次挥手

· 3 min read
Alex Chen
The main character of the story

三次握手是这样

第一次(客户端 to 服务端):我想建立连接,你听到吗? 如果服务端收到第一次握手的请求后,则可以确认:[客户端 to 服务端] 是畅通的。 客户端还不知道任何是否畅通的情况

第二次(服务端 to 客户端):我收到你的请求了,可以建立连接啊,你听得到吗? 此时,服务端可以确认的事情是:[客户端 to 服务端] 是畅通的。 客户端如果收到第二次握手的服务端回复后,则可以确认 [客户端 to 服务端], [服务端 to 客户端] 都是畅通的。

第三次(客户端 to 服务端):我听到你说可以建立连接了。 上面已经确认了[客户端 to 服务端] 是畅通的,这个包不会有问题。 此时如果服务端收到确认后,知道的事情有:[客户端 to 服务端],[服务端 to 客户端] 都是畅通, 而客户端也知道 [客户端 to 服务端], [服务端 to 客户端] 都是畅通。

好的,三次握手确认了双方畅通。

然后为啥要四次挥手呢

现时情况:双方建立了连接,可以互相发送数据 首先我这边想断了连接,那我第一次挥手,说:我要断开,从现在起我也不给你发数据了,

他那边收到了这个断开请求后,先发出一个确认包:好的,好的,我知道了, 我先收到这个确认后,就知道他收到了我的断开请求了。

然而因为他那边也是可以发送数据的,突然让他停下来,他也得把手上的事情干完啊,那对方等到手上没事情后(数据发完了),就会再发出一个:好的,我准备好了,断开吧。

最后我这边收到他的就绪信息后,现在大家都没事了,断开吧。

嗯,四次挥手就这样。

Reference:

戏说西游||TCP/IP协议的由来

为什么“三次握手,四次挥手”?

Leetcode - Median of Two Sorted Arrays

· 5 min read
Alex Chen
The main character of the story

对这题想到一个方法,既然是两个 Sorted Arrays, 用 Merge Sort 类似的归并方法组合两个数组就可以了, 根据总长度的奇偶抽取第 N 大的数值出来就完成啦。但这样做的话运行时间是 O(m+n / 2), 题目要求 O(log(m+n))

第一个想法就是二分, 参考了几个博文之后, 先准备一个 Kth 函数用于寻找两个 sorted array 的第 K 小的数, 然后中位数就很容易了, 反而一开始追求二分中位数似乎会有不少 corner cases

那先把问题换成两个有序数组的第 K 小的数值

有以下步骤

  • 有序 vector v1 和 v2, 求第 K 小
  • 二分思想是每次从 v1 和 v2 排除一半的可选元素
  • 有 x, y > 0 && x + y == k,
  • x, y 的取值也是有讲究, x = len(v1) / (len(v1) + len(v2)) * k, 这个意思是 len(v1) 占总 size 的百分比, 再乘以 k 的话就可以确保 x 的取值不会超出 v1 的数组范围, 这里简化了, 实际代码需要注意一些边界问题
  • 如果 v1[x] < v2[y], 则 v1[0 .. x] 的元素都不可能是第 K 小, 他们都肯定比第 K 的数值要小了, 我们则可以排除掉这些数值,
  • v1[x] > v2[y] 的话都是同样的思想
  • 调整 v1, v2 的长度, 下表值, k 的值等, 然后重复这些取值然后比较的步骤,
  • 调整完 size 和 下标后, 检查一下 k 是否下降到 1, 第 1 小的值是 min(v1[0], v2[0]), 还有如果其中一个 vector 的 size 下降到 0, 那可以直接返回另一个 vector 的第 k 个值
  • 如果是 v1[x] == v2[y] 的话, x + y == k, v1[x] == v2[y], 那这个数值已经是第 K 小了, 这里是一个 base case

大家可以 Leetcode 测试一下自己的代码 https://leetcode.com/problems/median-of-two-sorted-arrays/

下面是我提交的代码

打印蛇形数组

· 2 min read
Alex Chen
The main character of the story

唉, 不熟练连这样的题都不会入手。。

题目大概是这样 http://icpc.ahu.edu.cn/OJ/ContestProblem.aspx?cid=16&id=410 参考了 http://www.cnblogs.com/kaima/p/4773908.html

外部的 while 循环检查 number 是否到 N * N, 如果 N 为偶数则可以在这里停下, (最后四个位置刚好填完) 里面第一个 if 检查奇数 N 的情况(会填充剩下一个位置)

然后开始填充数组, 调节 x y 的坐标值填充一圈蛇形, 一圈后 x y 回归原点 缩小 size 变量 x+1, y+1 跳入内圈重复以上步骤又填充一圈, 直至跳出 while 循环

x y 走向

代码如下

韩剧《未生》

· One min read
Alex Chen
The main character of the story

未生、完生

一年内断断续续的看完了这部剧, 第一次看到『未生』这词完全想不到什么意思, 其实这是个韩国的围棋术语。『未生』对应『完生』, 完生其实就是双眼活棋, 未生就借喻职场新人了。

不同于某些套题作文剧, 是有共鸣在, 这励志鸡汤熬得不错。

《未生》剧照