Python 中的闭包

def f1(): l = [] def c(): l.append(1) def f2(): a = 1 def c(): print(a) a = 2 类似 f1 和 f2 中的闭包写法,之前总是在用了前者多次之后,再写后一种就报错,感觉很莫名其妙,明明都差不多。研究了下发现,其实这是 Python 闭包的 BugFeature,理解之后反而觉得这样的设计是合理的。 首先说 Closure,也就是闭包,特指内部的函数及其引用的超出本身作用域的对象,总是在函数嵌套时发生。在 f1 中,c 就是一个闭包函数,同时 l 也算作其中的一部分。因为 c 使用了 l 导致延伸了原有的作用域,所以才有闭包的产生。 再看 f2,如果我们只对 a 做 read 操作是不会引发问题的,由于 c 中尝试了赋值操作,才导致了 UnboundLocalError. 这是因为 Python 解释器会假定函数中赋值的变量是局部变量,而 c 中本身并没有定义 local 的 a 变量;其次,异常在 print(a) 时就会抛出,不会等到 a = 2 的执行。 那为什么 f1 没问题呢,是因为列表为可变对象,append 操作只是更新了里面的内容,并不存在赋值。 def f(): l = [] def c(): l....

01-29 · 1 min

关于 HTTP Auth

Auth 代表了 Authentication 和 Authorization 两个概念,也就是认证与授权。基于 HTTP,两者得以遵循一定的标准,SSL/TLS 之后,又出现了 OAuth 2.0,让授权也简单了许多。 Authentication 认证相对来说比较直接,核心就是对 Credential(e.g. username/password) 的验证。HTTP 提供了多种认证方案,比如最常见的 Basic auth, Digest access 和 Bearer. Basic auth 具体来说就是服务器用 WWW-Authenticate 表示需要认证,比如 WWW-Authenticate: Basic realm='Accessing to xx site',客户端则通过 Authorization 提供相关信息:Authorization: Basic Zm9vOmJhcg==,后面的一串编码是对用户名密码明文进行 base64 的结果,即可以直接从中 decode 出原始信息 foo:bar. 没有 HTTPS 的保护,这样很不安全,所以 Apache/Nginx 对 BA 的实现都会使用密码的哈希结果而不是原文,拿后者举例: http { server { location / { auth_basic "Accessing to xx site"; auth_basic_user_file /path/to/authfile; } } } 然后需要在 authfile 中保存 username/password pair,比如 sudo htpasswd -c /path/to/authfile user1,htpasswd 是 Apache 提供的专门用来生成 BA 使用的 Credential file 的工具。不用额外安装,我们直接用 openssl 代替:...

01-28 · 3 min

Spicks and Specks

Where is the sun That shone on my head The sun in my life It is dead It is dead Where is the light That would play In my streets And where are the friends I could meet I could meet Where are the girls I left far behind The spicks and the specks Of the girls on my mind Where is the sun That shone on my head...

01-20 · 1 min

水浒传之英雄本色

没想到 2021 年的第一篇博客是关于电影的,感觉很奇特。平时看电影最多就是上豆瓣评个分抖两句机灵,这次却想写一整篇,大概对于喜欢的东西废话就会变多吧。 一个好故事 《水浒传之英雄本色》讲述了林冲上梁山之前,和鲁智深相识结义并与朝廷决裂的故事。剧情流畅,引人入胜。 1. 起 开头就是一个小片段,林冲从插翅虎手中救回了高衙内,寥寥几笔便刻画出了林冲的武功和衙内的无赖,也为后来两人之间的矛盾升级埋下了伏笔。 后面又简单描绘了林冲的性格(武痴、不畏权贵)和生活状态(和妻子如胶似漆),平稳之中让人感觉巨变即将来临。 2. 承 这里主要开始写林冲和鲁智深相识相交到结拜成兄弟的过程,我觉得也是整个电影最好看的部分。两个英雄人物的性格碰撞,切磋武功又怕王祖贤饰演的妻子发现,十分欢乐。既有兄弟情义,又有夫妻恩爱。 巧妙的是里面还用武功的隐喻了林冲此时的立场:以退为进。鲁智深劝其罢官上梁山,但他认为只要足够忍让,仕途之路仍然可以走出一片天。 3. 转 与鲁智深告别之后,林冲迎来了人生的暴风雨。狡诈的高俅父子在明,阴险的陆谦在暗,栽赃诬陷,虽有丞相帮助,最后还是免不了发配充军。 探监这里王祖贤换了黑衣,发型也改变了 后面愈加悲惨,妻子被衙内觊觎已久,结果惨死刀下;而林冲自己也险些被手下的兵士所害,幸得结拜大哥及时来救。 在流放的军营里,林冲依然在以退为进,拒绝鲁智深的劝说,甘愿挨饿受罚,对朝廷还抱有幻想。 4. 合 最后,得知丞相妻子皆死,林冲终于下了复仇的决心,但他首先做的是和鲁智深决裂,支走对方,独自面对陆谦大军。这里两人的内心各有表达,林冲自言自语重复了结拜时说的话:有福同享,有祸我当;而鲁智深则把疑问都抛给了坐骑,虽然马儿再三摇头,却还是决然返回:为兄弟,没有面子就没有面子。 结局自然是两人手刃敌人,终于齐上梁山。 英雄本色 越写越觉得一部电影的剧情逻辑和人物形象重要,那个时候的特效很落后,但用几个简单的场景和对话就可以把每个人的性格和内心写活,看起来回味无穷。除了故事本身,整个片子的阵容也超级强大: 主角 林冲:梁家辉的古装扮相极其帅气(发髻加高马尾),和新龙门客栈中的形象不相上下 鲁智深:徐锦江把这个角色塑造地非常到位,还被提名当年金像奖最佳男配角 妻子:一袭白衣的王祖贤绝美,柔情似水的表演让人难以忘怀 反派 高俅父子:老戏骨刘询自不必说,难得的是带胡子的奸人角色(不知道是不是唯一,老爷子一向是有胡子善没胡子奸的);单立文的疯癫演技独树一帜,抛开角色,演员本身还是很正直的(从网上看),还给主题曲作了词 陆谦:林威很适合这种反面形象,在结尾决战的时候几次规整官帽的动作,把陆谦对功名利禄的执念体现得淋漓尽致 客串 仇五:刘青云客串的小角色,为报恩林冲而死,戏份少但很精彩,难怪后来成为影帝 丞相:午马轻松出场两次,每次都会让我想起燕赤霞 其他 导演:陈会毅,港片的武指老炮 配乐:胡伟立,绝对的大师 看完电影的光辉时刻,总是不想跳回生活的平淡点滴,但两者难免要糅和,英雄本色要面对的是漫长人生路的每一天。这部戏还有一点可贵的地方就在于演员自身也是很有性格魅力的人。之前看芒果 TV 的一路成年,梁家辉和徐锦江都是很爱家爱孩子的人,但前者也是时而暴躁的硬汉,而后者身上则充满了艺术家的多愁善感。还有息影多年的王祖贤,自己去买菜的市民刘先生。那个时代的香港影星总是不乏传奇色彩。 资源 爱奇艺上的港片资源不算少,但这部的质量很差。YouTube 有高清的在线版本: 可以用 yt-dlp 下载到本地。 原声带比较好找,QQ 音乐和网易云应该都有现成的资源。 References 水浒传之英雄本色 - 豆瓣

01-14 · 1 min

关于 SSH 端口转发

SSH 的端口转发很实用,但我总觉得难以理解和记忆,直到最近才有所好转。 因为又派上用场了。以前基本只做做内网穿透,现在更多地拿来绕过防火墙。自己的服务器,大多数端口虽然都是被禁用的(至少禁止入网,这也是正常的安全措施),但是想要连接的话直接本地端口转发就可以了。 TL;DR 本地端口转发在当前机器上设置,然后从本机出发,通过另一台机器,连接其他的机器。适用于防火墙的绕过、多重 SSH 登录等。 远程端口转发在当前机器上设置,然后从另外一台机器出发,通过当前机器,连接本机或者其他的机器。适用于 NAT 网络穿透、暴露内部网络服务等。 本质上都是先建立 SSH 会话,形成隧道,然后在上面进行正向或反向的数据传输。 Local Port Forwarding 为什么叫做本地呢,我想有两个原因: 转发的端口在当前(执行 SSH 命令这台)机器上 请求是从当前机器发出的 当前机器就是我的笔记本,另外一台是服务器。比如,在服务器上部署一个应用,开放给 8000 端口,但是被墙掉了,没办法在本地调试,怎么办?防火墙肯定开放了 SSH 登录的端口,比如 22,那么就让请求从本地的端口发送到服务器的 22 端口,再转发到 8000 端口,最后原路返回。我可以设置本地的端口也是 8000,这样直接用 localhost:8000 来访问应用就好了。 转发的重点在于本地的 8000 端口和服务器的 22 端口之间,因为请求到了服务器之后可以给应用的 8000,也可以给其他的机器,只要服务器能连接到: # ssh -L local_port:dest_addr:dest_port server # Local 8000 < -- > Server 22 < -- > Server 8000 # -fNT 让 ssh 不要打开服务器 shell,并且转为后台运行 # server 隐含了使用 22 端口登录,当然也可以在 ssh config 中设置任意登录端口 ssh -fNT -L 8000:localhost:8000 server 注意这里的 dest 对应的 src 是 server,也就是说 localhost 及后面的 8000 都是 server 的 IP 和端口。可以理解为 server 是中介,整条通路是 local -> server -> dest....

12-22 · 2 min