Run ssserver on VPS

Published on:

VPS 上面好早以前用过 docker 跑了一个 container 运行了一个 ssserver, 是从 debian 基本系统创建, 然后手动安装各种软件弄好的. 最近朋友升级了 docker, 那个工作有点问题了,就重新搞了一下, 发现现在好方便.

我用的是这里提供的 dockerfile https://github.com/EasyPi/docker-shadowsocks-libev, 他的例子里面使用了 docker-compose 来创建, 发现很简单, 不过遇到了一个问题, 说一下解决办法.

这个 docker 本地监听的端口是固定的 8388 不能修改, 例如 docker-compose.yml 里面


server:
  image: easypi/shadowsocks-libev
  container_name: wd-ss
  ports:
    - "HOST_PORT:8388/tcp"
    - "HOST_PORT:8388/udp"
  environment:
    - METHOD=aes-256-cfb
    - PASSWORD=5ouMnqPyzseL
  restart: always

需要配置的是 HOST_PORT METHOD PASSWORD 这三个变量, 然后我还指定了 container_name 方便以后的操作, 不指定会自动产生一个.

启动服务之后,可以使用 docker logs wd-ss 来看 log, 类似于下面, 这个 docker 启用了 udp relay 和 tcp fast open, 差不多也就够了.


 2017-06-09 03:13:17 INFO: using tcp fast open
 2017-06-09 03:13:17 INFO: UDP relay enabled
 2017-06-09 03:13:17 INFO: initializing ciphers... aes-256-cfb
 2017-06-09 03:13:17 INFO: using nameserver: 8.8.8.8
 2017-06-09 03:13:17 INFO: tcp server listening at 0.0.0.0:8388
 2017-06-09 03:13:17 INFO: udp server listening at 0.0.0.0:8388
 2017-06-09 03:13:17 INFO: running from root user

如果想要开启更多选项, 可以在 compose 文件里面使用 command 自定义启动命令


  command:
    ss-server -s 0.0.0.0
              -p 8338
              -k 5C4D5403-31C9
              -m aes-256-cfb
              -t 30
              --fast-open
              -u
              -a nobody

自己实验过程中, 如果可以随时删除自己的 container 重建, 将来 ss 升级的话, 只需要把 image 更新一下,然后删除再新建一下 container 就好了.用起来还是相当简单方便的.

Meetings and meetings

Published on:

前几天海龙 在 twitter 的提了一个问题“这个世界上有喜欢开会的人吗?能和我说说理由吗?”。作为开了很多会的人,由不住想说两句。

    首先,高质量的会应该具备什么呢?我也没看过《罗伯特议事规则》这样的书(放在 kindle 里面好久了一直没看过,汗颜。。),就是自己按照自己参与的情况总结下:
  • 会议前必要的沟通,好确认是不是需要你参加。当然也有一定可能性组织会议的人确认需要你参加而不做沟通(当然也不排除判断错误的时候 QAQ)。
  • 组织会议的人做好前期调研,会议讨论的一些相关方案的基本情况应该需要比较了解。避免好容易召集齐人之后,发现要讨论的内容本身自己互相矛盾,或者需要参会的人没有通知等情况。
  • 邮件通知与会人会议要沟通的内容,和希望达成的目标,让大家提前了解事情的原委。也给大家一个机会提前确认下是不是真的和自己有关系。
  • 有了希望达成的目标,就应该会比较明确具体需要谁参与,比如想要一个明确的决定的时候,却约一个不能拍板的人来,这会议注定不能成功。
  • 会议中有可以控制会议节奏的人主持。能适时的阻止一些无关话题,扯皮,控制会议节奏,避免开大长会和会上吵架。
  • 会议中有人记录会议记录,结束后有人会把会议记录和结论(这个很重要,没有结论的会就是没必要开的会)发给所有人。

下面列几个我作为技术人员常见的一些烂会。

产品总监派一个刚入职几天业务都没摸清的人召集一帮干了好几年的工程师开会。这种情况下,产品经理大概率会被工程师各种怼,因为他不可能真的熟悉产品,工程师提到的很多可能的问题都不太可能圆满回答,最后会发现要讨论的问题各种依赖性,A 功能不确定的情况下,B 功能可能直接就不存在而没必要讨论了。最后会导致会议非常低效。这个时候所有人都会不爽,技术工程师会认为浪费他的时间,产品经理会认为这些人好难配合。其实锅应该是在产品总监头上。

跨部门的会议。很多时候莫名其妙就招呼你去开会,到了之后也不知道是讨论什么的,最后听半天发现貌似和自己一毛钱关系都没有,浪费几个小时。当然浪费的是你的时间,组织会议的人其实是有收获的,他明白这事情和你无关。

头脑风暴会议当作需求讨论会来开。有时候对方可能根本没有明确的想法,你当成最终需求讨论半天指出来其中各种问题,最后发现其实他们根本就确定怎么做呢。这种情况其实就是那个网传的“产品经理找你聊一天,他的需求有了,你的程序还没写”的情况。毕竟需求会的优先级会比头脑风暴要稍微高一点。

如果作为组织者,就是尽量做到前面提到的好的会议应该具备的条件,避免浪费别人时间。作为参与者,如果有能力,遇到有问题的会议,应该想办法协助会议组织者把会议变高效,提高效率的同时,自己也会节省不必要的时间,我经常这么干,毕竟年轻人不容易。。。。当然,我有时候不一定那么有耐心,遇到垃圾会有时候直接就走了,留他们继续浪费时间。

再回到海龙的问题,我的回答是有些人为了合理的浪费时间,是会喜欢开会的,因为这样会让别人觉得他的时间安排很充实,因为整天不在座位,在忙。不知道各位开会的时候有没有遇到一些人全部时间都是在刷手机,只是偶尔说一两句话?这些人就是我说的这种人。我如果遇到我没兴趣的会或者和我无关的会议,我会直接和组织的人申请离开,如果确实后面和我有关系,那麻烦到了时间点叫我(当然你也得保证下到时可以随叫随到,避免浪费其他参会人的时间等你),当然,呃…… 如果我碰巧也想合理的浪费一下时间。。。。

这些人一般都需要是 leader,至少有人在给他创造 GDP 的,否则一个手头很多工作要干的人,你让他开这种无意义的会他自己也不答应,否则其他工作完不成无法交代的。不过某种意义上讲,这些人也是有贡献的,至少能组织一些人贡献 GDP 就是贡献。

感觉跨职业跨部门的会比较容易产生垃圾会,因为看问题角度不一样,有时候会比较难互相理解。我们技术人员很多时候开会,都是找一块白板,画几个图,大家就都明白了,很快就能出决议,不能定的一般可能是需要 leader 拍板的。

同一个部门的会大家会接触比较多比较容易妥协,能接受自己多花点时间或者吃点小亏来完成一个事情。这其实也是所谓的拓展,团队活动,年会想要达到的目的,如果大家都很熟悉的情况下,就比较容易站在对方的角度想问题,遇到事情容易妥协。

上面提到的这些问题其实越大的公司问题越多,反而小公司比较少,因为头绪少,并且大家都比较熟悉的缘故。当然实在遇到一个比较弱的会议组织者,烂会也不可避免。

Something about cruise tour

Published on:
Tags: cruise travel

之前知道邮轮游一直没有体验过,据说是在上面各种滚来滚去看书,因为手机没有信号,没有网络。前几天体验了一把,总结一下。

一句话总结

这上面有你讨厌的所有因素,大妈,广场舞,广场卡拉 ok,小孩子,无序,占座,插队,甚至最后一天还目睹了两起吵架。

邮轮游玩什么

我参加的是歌诗达幸运号(Costa Fortun),邮轮上面估计 80% 都是各种大爷大妈,带着女儿外孙。你可以想象一下,平时最不喜欢的组合在这里最全了。

邮轮上面有免费的自助餐和一些特别的餐食,比如批萨,面条,猪排什么的。也有收费的餐食,当然你可以不去。酒和软饮都是收费的,开饭的时候有免费的白水给你喝,屋子里面是没有的。

邮轮上面一般有大量的娱乐设施,比如赌场,游戏机,泳池,桑拿,剧场等。还定期有各种娱乐活动,比如猜个字啊,跳个舞什么的。所以第一次去还是可以看个新鲜的,尤其可能还有一些漂亮的陪玩 mm,看着也还可以。游戏机赌场是收费的,恩。

此外剧场每天基本都会有一场大型的演出,30-40 分钟,可以让你打发时间。但是剧场虽然每天演出内容不一样,但是演员总是那一波,看多了其实也会腻味。

房间里面也有电视,不过我观察电视都是反复重播录下来的一些电视,然后有一个电影台还是只有那么几部反复重复播放,《x man 天启》我看了不下 10 遍。

小孩也有人给带着玩游戏,有专门的儿童俱乐部。还有健身房,健身房是我唯一对这次邮轮活动满意的地方,当然肯定不是对环境满意,毕竟里面充满了大爷大妈,满意的地方主要是在设备,设备真心不错。浴室和换衣间地板异常干净,比起我家楼下的奥力,简直天上地下。

邮轮一般有那么1,2天是下船,我们这次的安排很屎,景点很无聊,低接导游也只是对购物有兴趣,购物店虽然不贵,但是东西比较少,挺没意思的。

让人反感的几个瞬间

排队上邮轮的时候,过安检的时候就一条队排的特别粗,到了最后那变细互相挤着往前走。我们后面有个阿姨就各种急着往你前面走,我老婆发现之后就故意挤着不让,我看的笑死,呵呵。

第一天必须做逃生演习。有个大爷一家推着小车带着孩子,孩子可能没一会睡着了。而演习是需要所有人参加的,所以就不得不等比较慢的人。大爷就生气了,开始呵斥工作人员,「孩子都睡着了,啥时候开始」之类的,声音巨大。工作人员大都是外籍,估计也吓了一跳。最后结束的时候,大爷还过去指着那个工作人员不知道说了什么。

剧院演出,基本前三四排上面都是东西占座的。除非你提前半个小时到。另外就是各种小孩大声说话也没人管。有时候酒吧做游戏,工作人员都明确说了游戏可能比较激烈,让大家把小孩弄走,但是看着一个女的抱着小孩几次被劝离之后还是要上去玩,貌似还是上去让小孩参与。

昨天有个游戏,几个被淘汰的大妈,悄悄的跑回去继续参与,也有跑回去被发现之后赶走,再次跑回去的,当着一百来号人目睹就那么做,真的无语。

今天下船之前大家集中在一个地方等着,有个姥爷带着孙女玩气球。有个哥们玩心重,带了个面具就冲那小孩过去了,小孩吓的赶紧跑到了姥爷后面,那个哥们就走了。过了半分钟小孩反映过来开始哭,那姥爷就开始不爽了。后来他们全家,追着那小伙骂,最后把面具也抢过来了,还要护照说要以后有啥毛病要找他。纠缠了能有10分钟。

这只是记得起来的几个,反正年轻人真的不建议去邮轮了。如果是自己父母,倒是可以推荐去,他们应该喜欢。

My way to keep fit

Published on:

目前第一阶段减肥基本告一段落,后面目标是保持目前体重 6 个月。

先聊聊结果

2014 年 9 月份前,我的体重最高到 98kg,甚至有时候超过了 100kg。第一阶段减肥可能截止到 2016 年中,减到体重大概是 92kg。第二阶段开始于 2016 年 2 月底,截止到今天体重 80kg。整体算下来减掉 40 斤。

第一阶段

2014 年开始我发现一种比较简单的减肥方法,就是不吃或者少吃晚饭。

这个方法应该不一定对所有人适用。我估计应该只对 BMI(Body Mass Index, 身体质量指数,注意和体脂率不是一个东西)比较高的人有用吧。

我当时 BMI 是 98/1.77^2=31.28 是属于比较高的,坚持了上面的方法半年之后,大概最瘦的时候是 28,我查了是刚好脱离了肥胖那一档,进入了过重。

我当时所在的公司的上班时间是 10:00 - 19:00,但是经常出现 20:00 以后才从公司走的情况,这样我到家经常是 21:30 或者 22:00 以后。这个时候吃晚饭就太晚了,基本吃饭完了就睡觉了。并且,中午吃饭到这个时候,一般其实已经饿过劲了,那个时间反而没有那么饿了,我就慢慢开始晚上到家之后只吃几个水果。后来慢慢转为不吃东西,或者只吃很少的水果。有时候也会遇到快下班的时候非常饿,这个时候吃点小零食,也就可以了。这种方式减肥,早上和中午基本不控制自己,还是吃的比较好的。

上面说了,这个阶段减掉了大概 10 多斤。中午饮食基本不控制,晚上不吃,或者很少吃(一个月有那么一两次推不开的)。

第二阶段

大概是从今年 2 月底从日本回来,开始实施,方法是锻炼加节食。

锻炼的内容是 60 分钟椭圆机(我用的机器难度是 5,不同机器可能不一样),30 分钟运动后拉伸,30 分钟游泳。大概是每周 1,2,4,5 去,一周会休息三天。锻炼毕竟比较枯燥,所以需要中间休息一下调剂一下心情,如果你的体力耐力跟的上,可以不休息。

上面的强度下来,进度大概是一周 3kg。我的情况 3 月 25 是 88.6kg,5 月 2 是 81.7kg,5.5 是 80kg。为什么比较慢呢?在这两个月内,我参加了一趟邮轮游大概一周,去了一趟沈阳,大概一周,还去了一趟日本大概一周。所以如果坚持应该可以更快,但是快速减重我感觉应该可能会有副作用,所以我也基本也是控制减一点,保持几天这样子,不让这个减重太快。另外,这段时间我是全职减肥,所以没有工作上面的压力,可能速度相对快一点。

方法细节

MHR

按照一些理论,在有氧运动一定时间 T 之后,保持一定的心率 HR 继续运动,就会开始消耗脂肪。所谓的 fat burning zone (搜索到的,仅供参考)。

对于 T,我看有的说是 20 分钟,有的是 40 分钟。我一般的做法是持续运动 40-50 分钟,不超过一小时。

对于心率,先看下面的公式


MHR(最大心率) = 220 - age
MHR = 206 - (0.88 x age)

上面是最大心率,有多种算法最后应该结果大致有个范围,然后你的减脂的 HR 范围就是 MHR x (0.7 到 0.8) 之间。我算出来我的是大概 130-145.

所以注意并不是越累越好,比如天天跑 5km 还追求速度,那个思路不对,那个不是减肥。只要心率到了加持续时间够长。,不管做什么都减肥。

节食

如果想要减脂,必须要节食,并且节食之后,我发现不运动体重也会降,直到降到一个平衡点。

节食并不是一下子就从原来中午晚上吃两碗米饭变成只吃一个苹果,这个也是应该有个循序渐进的过程,要不不说身体是否能接受,你自己就坚持不下来。

我的建议是,逐步减少饭量,花 1-2 个月来完成这个过程,一定要给自己定一个什么时间点达到什么目标的方案,否则面对一个自己都觉得无法达到的目标,也会容易被各种诱惑吸引,然后放弃。

节食期间,并非就一直得是清淡饮食,偶尔吃一次大餐也不是不行,但是最好安排在中午,并且吃了之后第二天早餐午餐一定要减少量。另外注意是「偶尔」,千万别当成常态。

此外,也得注意要按时吃饭,节食本身就很痛苦了,如果不能按时吃饭,比如过了平时饭点再吃,容易吃多,影响节食效果。

我自己的方案,如果今天上午不出门,那就最多喝一杯牛奶做早餐。如果要出门,可以接受大概半个馒头那么多的饮食量。中午也类似,如果不出门就少吃,如果要出门,可以适当比平时多一点点,避免晚上的时候很难熬,或者路上出现低血糖。

我自己控制的结果,是在中午大概3点一顿自助餐的基础上,晚上6点又有不能推掉的酒局的情况下,中午一杯啤酒,晚上一杯红酒,然后第二天重量维持不变。自己感觉还是挺有成就感的,当然也很痛苦。

我目前体重还没有到平台期,还不清楚节食结束之后反弹的情况,但是我自己的打算是平台期或者达到我的目标体重之后,我再继续维持低饮食量一段时间巩固下,把自己的饮食习惯培养好,不再能暴饮暴食的情况下,应该是可以适当放开饮食的。

    总结下:
  • 节食要循序渐进,不要一次就到位,食量可以比如每周减 1/4 的节奏安排。
  • 设定自己的目标,一阶段一阶段完成,不要一次设定一个看着无法做到的目标
  • 饮食要准时定量,实在受不了的时候,可以允许自己来一次暴食(不要暴饮,尤其是甜的饮料,酒等),但要注意控制次数
  • 毅力坚持很重要。我节食期间参加各种自助餐,火锅,聚餐等都能很好的控制自己的食欲。

关于低血糖,特别讲一下,节食非常容易产生低血糖,建议按照自己的体力,健身之前最好吃一口东西(不要多),或者随身携带一些吃的,一旦感觉低血糖头晕,就补充一点。别产生什么危险。

低血糖的时候,也会影响你做事情的效率,会发现什么事情都不想做,所以这个时候最好就吃点吧,不过要注意是这也是有控制的吃。

跑步机 vs 椭圆机 vs 动感单车

    我自己家里买了一台动感单车,实际实践过之后,用这个有几个缺陷
  • 自己练没有动感。在操课房里面教练会带着不停的变换速度,动作,一方面让你觉得没那么无聊,另一方面也是能增加运动量。
  • 自己练容易损坏脚踝和膝盖。我自己在家练的时候,基本就是站上面运动 30+ 分钟,脚一直在单车上面脚尖踩着,练完之后脚会疼痛。

我其实挺喜欢在外面跑步,尤其早上,但是因为体重大,好几次都是跑一周之后双腿膝盖会开始疼痛,只好作罢。健身房里面的跑步机冲击比路面跑步小,可以试试看。

最近尝试了跑步机上面跑,坚持 2 周之后,还是出现了一只腿的膝盖疼痛,只好暂停。开始尝试椭圆机。

跑步机上面跑强度比椭圆机肯定强很多,跑步机上面在一个不快的速度下面,我持续跑 15 分钟之后,心率就会达到 150,其实已经有点高了。

    跑步机的几个问题
  • 容易心率过快
  • 不方便听音乐看片子分散注意力
  • 不容易不间断坚持跑 30 - 40 分钟
  • 膝盖损伤
    最后发现椭圆机实在是很不错
  • 运动速度慢,不妨碍你看片子听音乐(这个非常重要,否则坚持50分钟很难)
  • 速度恒定,也就是心率恒定,你只需要选择一个适合你的减脂的心率的难度就可以了
  • 对膝盖冲击比较小

我用实际使用的就是椭圆机 Elliptical Trainer。一次 60 分钟,控制心率在 140 左右。高了就换近一点的把手,低了就换远一点的。

运动后拉伸

这个一定要做,可以参考 keep 这个 app 里面的一些教程做,另外就是自己看着健身房的设备练练。注意设定好节奏,比如一组 10 次,做 3 组。

这个是拉伸,不是力量训练,所以不需要挑战自己的极限。控制好设备的重量。

饮食注意

我本身血压高,所以需要低盐。然后减脂的话,一般的讲法是不要吃或者少吃和糖类有关系的食物,比如糖,西瓜这些,以及很容易转换为糖类的食物,比如谷物,大米这些。可以吃肉类(瘦肉或者白肉,比如鸡肉鱼肉)。

我以前基本没炒过青菜,这次发现光是做到不难吃的话,其实很简单。

  • 不用水煮直接凉拌:黄瓜,西红柿等,莴笋
  • 白水煮了就能接受的:西兰花,菜花
  • 水煮之后过油炒一下加点盐或者酱油的:油菜,蘑菇,小白菜,菠菜
  • 直接过油炒一下加盐或者酱油:芹菜

之前看了一本书,里面讲到几个低盐的方法,就是比如放入火腿肠等本身自带咸味的食材,或者往酸的方向走。对于凉拌菜,可以适当考虑加一点醋,发现还挺不错的。

Update

有上面这几招,应该可以让你短时间不会吃腻了。我中午基本就是吃一盘青菜,不吃主食。

2017.6.9

更新一下, 从停止运动到现在已经大概一个多月了, 之前最低到了 78kg. 这一个月发现如果还按照之前的食量, 体重还会降. 但是我不打算继续让它降的, 所以也开始提升食量.

最近两周我还出去国内玩了一趟, 吃饭吃的也挺多的, 时间也不固定, 到了当地还会尝试喝当地的一些米酒啤酒之类的, 到今天早上称重是 79kg. 感觉还可以.

Use org mode to publish blog

Published on:
Tags: org-mode org

a test

啊哈哈哈哈,超棒唉。markdown 里面写代码都没有高亮,org 里面是可以把代码部分高亮的。 效果可以看 这里

Title1

title2

  • list1
  • list2
  • list3

import sys

class Hugo(object):
    def __init__(self):
        pass

hugo = Hugo()
print(hugo)
print("just a test")

Migrate blog to hugo

Published on:
Tags: hugo hexo blog

折腾了好几天,把 blog 从 hexo 迁移到了 hugo 上面。hexo 是使用 nodejs 写出来的,hugo 是使用的 go。主要基于下面几个原因吧。

  • 个人不太喜欢 nodejs 那一坨依赖。
  • hugo 也比 nodejs 速度快很多。
  • hugo 用起来比较简洁。

首先写了一个迁移工具 hexo2hugo。网上还有一个 nodejs 版本的迁移工具可以参考。其实就是简单的把头部信息处理一下就可以。我还有一些特殊需求,比如把老早以前的一些 html 格式的文档顺道处理一下格式,还有一些小的修正和兼容工作,所以自己写了一个。另外也主要是好久没有写代码了,熟悉下。。

把文档迁移过去之后,找了几个主题看了一下,发现没有很喜欢的,就本着蛋疼的原则,把原来用的主题也迁移过来了,这个花的时间比较长一点。主要还得熟悉 hugo 的模板语法,还得想办法适配 hugo 的体系。比如 hugo 里面没有 archive 一说,不过通过万能的 google 搜索到了一个解决办法,也勉强还好。

目前这个 blog 已经是由 hugo 产生了,和以前外观,访问地址完全一模一样,rss 地址都一样。我测试了 google 里面的搜索结果,是都可以跳转的。今天算是基本都迁移完毕了。

这几天没事也总想记录一点想法,但是无奈新本子上面的 hexo 挂了,又不想搞 nodejs 那一坨依赖,就折腾了这个事情。不过折腾完毕之后发现想记录的事情都忘记了,nnd。

Upgrade kernel to 4.9 for linode

Published on:

bbr 那么牛逼,赶紧赶一个潮流。其实我之前用了 kcp,也是类似的东西,不过那个要求服务器端和客户端都需要跑 kcp 服务才可以。bbr 就不用了,只需要服务器配置好就可以了。

Linode 实际上已经提供了 4.9 的内核。打开 Dashboard,然后点击你使用的 profile 右侧的 edit,在出来的界面里面,Kernel 右侧的列表里面,有个 4.9 的选项,不过我测试这个内核并不能打开 bbr,不知道是怎么回事,有兴趣的可以试试看,要注意选对架构(就是 64 还是 32)。

所以还是需要自己装内核。debian 官方已经打包好了 kernel 4.9,访问 http://mirrors.kernel.org/debian/pool/main/l/linux/ ,然后找到适合自己的 linux-image-4.9,我的是 http://mirrors.kernel.org/debian/pool/main/l/linux/linux-image-4.9.0-1-amd64-unsigned_4.9.2-2_amd64.deb ,下载到 vps 上面。

然后执行 sudo dkpg -i ./linux-image-4.9.0-1-amd64-unsigned_4.9.2-2_amd64.deb,最后应该会提示一个错误,缺少依赖的包。这个时候执行 sudo apt-get -f install,会提示安装缺失的包。

然后,还需要安装 grub。看你的情况。就刚才 profile 编辑的页面里面,kernel 右侧的选项里面,你看看你的是 grub2 还是 pv-grub

  • grub2: 参考这个

    $ sudo apt-get install grub2
    $ sudo update-grub
    
  • pv-grub: 参考这个

    $ sudo apt-get install grub
    $ sudo mkdir /boot/grub
    $ sudo update-grub
    

然后在 profile 编辑页面里面,kernel 右侧选择对应的 grub 选项,重启 vps 就可以了。如果启动失败了,就在这个选项里面,选择之前的选项重启就可以恢复。

Python __new__

Published on:
Tags: python

翻译一点 https://www.python.org/download/releases/2.2/descrintro/#__new__ 有些感觉还是挺生硬的,方便自己理解吧。

__new__ 的一些规则:

  • __new__ 是一个静态方法。定义它的时候并不需要执行 __new__ = staticmethod(__new__),因为它的名字就包含了这个含义(这个对于类构造方法来说是个特殊的函数)
  • __new__ 的第一个参数,必须是一个类,其余的参数是留给构造方法的。
  • 覆盖了基类的 __new__ 方法的类有可能会调用基类的 __new__ 方法。传递给基类的 __new__ 方法的第一个参数,应该是覆盖基类的 __new__ 方法的类,而不是基类,如果传递了基类,你得到的将是基类的示例。
  • 除非你想要按照后面两条描述的方法来使用,否则 __new__ 方法必须要调用基类的 __new__ 方法,这个是创建你的对象的实例的唯一方法。子类的 __new__ 方法可以从两个方面影响产生的实例:传递不同的参数给基类的 __new__,以及修改基类产生的对象(例如初始化一些实例变量)
  • __new__ 方法必须返回一个对象。并不一定必须返回一个新的对象,虽然通常都那么做。如果你返回一个已经存在的对象,依然会有对于 __init__ 构造函数的调用。如果你返回一个其他函数的对象,那个对象的 __init__ 也会被调用。如果忘记返回,python 会给你返回 None,你程序的调用方也许会觉得很奇怪。
  • 对于不可变对象,__new__ 可以返回一个之前缓存的对象。对于一些比较小的 int, str, tuple 类型就是这么做的。这也是为什么他们的 __init__ 什么都没做:否则之前缓存的对象会被 init 很多次。(另外一个原因是本身页没有东西可以给 __init__ 初始化的了,__new__ 返回的就是一个已经初始化的对象)。
  • 如果你想要给一个内置的不可变类型增加一些可变的状态(例如给 string 类型增加一个默认的转换方法),最好是在 __init__ 方法里面初始化可变状态,而不要在 __new__ 里面。
  • 如果你想要修改构造方法的签名,一般需要覆盖 __new____init__ 方法来接受心的签名。然而,大部分内置类型都会忽视自己不用的参数,尤其是不可变类型(int,long,float,complex,str,unicode,tuple)都有一个假的 __init__,而可变类型(dict,list,file,super,classmethod,staticmethd,property)有一个假的 __new__。内置类型 object 有假的 __init____new__ (给其他对象继承)。内置类型 type 在很多方面都很特别,请参考 metaclasses。
  • (这条和 __new__ 没关系,但是页应该了解一下)如果新建一个 type 的子类,实例会自动给 __dict____weakrefs__ 预留空间( __dict__ 在你使用前不会初始化,所以你不需要担心创建的所有实例被一个空的字典所占用的空间)。如果不需要这个多余的空间,可以给你的类设置 __slots__ = [](更多信息可以参考 __slots__
  • Factoid: __new__ 是一个静态方法,不是类方法。我开始的时候觉得他应该是一个类方法,and that’s why I added the classmethod primitive。不幸的是,对于一个类方法,在这种情况下面 upcalls 不工作,所以我只好把他设计成一个第一个参数是一个 class 的静态方法。讽刺的是,there are now no known uses for class methods in the Python distribution (other than in the test suite). I might even get rid of classmethod in a future release if no good use for it can be found!

Python inherit and super

Published on:

又学习了一个 python 的继承。有很多帖子都有介绍,比如理解 Python superpython super()

先看一个例子,这个是第一个文章里面的。

class Root(object):
    def __init__(self):
        print("this is Root")


class B(Root):
    def __init__(self):
        print("enter B")
        super(B, self).__init__()
        print("leave B")


class C(Root):
    def __init__(self):
        print("enter C")
        super(C, self).__init__()
        print("leave C")


class D(C):
    def __init__(self):
        print("enter D")
        super(D, self).__init__()
        print("leave D")


class E(D, B):
    def __init__(self):
        print("enter E")
        super(E, self).__init__()
        print("leave E")

e = E()
print(e.__class__.mro())

# results:
# enter E
# enter D
# enter C
# enter B
# this is Root
# leave B
# leave C
# leave D
# leave E
# [<class '__main__.E'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.Root'>, <class 'object'>]

没有什么问题,所有的类都做了初始化,很完美。接着再看一个例子,这个例子其实是上面第二篇文章里面的。

class A(object):
    def __init__(self):
        print("enter A")
        print("leave A")


class B(object):
    def __init__(self):
        print("enter B")
        print("leave B")


class C(A):
    def __init__(self):
        print("enter C")
        super(C, self).__init__()
        print("leave C")


class D(A):
    def __init__(self):
        print("enter D")
        super(D, self).__init__()
        print("leave D")


class E(B, C):
    def __init__(self):
        print("enter E")
        super(E, self).__init__()
        print("leave E")


class F(E, D):
    def __init__(self):
        print("enter F")
        super(F, self).__init__()
        print("leave F")


f = F()
print(f.__class__.mro())

# results:
# enter F
# enter E
# enter B
# leave B
# leave E
# leave F
# [<class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]

我发现和文章里面贴的结果不一样,里面缺少对 C,D,A 的初始化。琢磨半天才弄明白,主要原因就是,AB 其实也是继承自 object,然而我们并没有调用 super 来初始化,所以只需要加上就可以了。

class A(object):
    def __init__(self):
        print("enter A")
        super(A, self).__init__()
        print("leave A")


class B(object):
    def __init__(self):
        print("enter B")
        super(B, self).__init__()
        print("leave B")


class C(A):
    def __init__(self):
        print("enter C")
        super(C, self).__init__()
        print("leave C")


class D(A):
    def __init__(self):
        print("enter D")
        super(D, self).__init__()
        print("leave D")


class E(B, C):
    def __init__(self):
        print("enter E")
        super(E, self).__init__()
        print("leave E")


class F(E, D):
    def __init__(self):
        print("enter F")
        super(F, self).__init__()
        print("leave F")


f = F()
print(f.__class__.mro())

# results:
# enter F
# enter E
# enter B
# enter C
# enter D
# enter A
# leave A
# leave D
# leave C
# leave B
# leave E
# leave F
# [<class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]

这样就完美了。目测这个会是一个隐藏的坑。