• IMAP 是通信协议,和 HTTP 是一个性质,但 IMAP 不是储存格式。

    Email 的流行存储格式可能是 mbox(服务器较少用), Maildir(较常见), 也可能是任意的邮件服务器所自定义的格式 (比如存进 SQL 数据库什么的). 具体要看你所使用的邮件服务器了。按照 LZ 目前提供的信息... 还无法判断。

  • Fedora14 下 如何安装 rails3? at 2013年06月07日

    RVM 还是挺友好的:http://ruby-china.org/wiki/rvm-guide 其中 curl 开头的那一行可以考虑换成 rvm 官网的:curl -L https://get.rvm.io | bash -s stable --rails

  • 真的不是手写输入把 6 月写成了 8 月么 - -

  • 如果这个 head 确实不需要 merge 回去,搜了一下发现这个:http://stackoverflow.com/questions/3688263/mercurial-beheading-a-head 但愿有用。

    注:我自己以前稍微用过一阵子 hg, 但已经很久不用了所以很生疏。但愿我对 head 的理解没错。

  • Object class 求教 at 2013年06月04日

    Object 这个对象是 Class 的实例,而 Class 的超类 (Class.ancestors) 中包含 Object 类。

  • Ruby 的方法调用好像野马 at 2013年05月31日

    #31 楼 @iBachue 我在 #30 楼 刚好回复了。Foo.barfoo.bar 取出的不是函数,分别是未绑定方法和已绑定方法。

  • Ruby 的方法调用好像野马 at 2013年05月31日

    顺便,我觉得还是得稍微说明下:把前面 #17 楼 的代码换成 Python 的大致等价物:

    class Foo(object):
        def bar(self):
            return 'bar'
    

    接下来 Foo.bar 返回的不是函数,是未绑定的方法 Foo.bar(1) 并不会返回 'bar', 而是会抛异常。

    Foo().bar 返回的也不是函数,是已绑定的方法。

    所以我所理解的 Python 在"函数是一等公民"这个特性上更优秀的地方,仅在于函数/绑定方法/未绑定的方法的调用方式是与常规的方法调用的语法完全相同的,都是后面直接加一对括号。而 Ruby 更加地以对象为中心,就得用 func.call()func.().

  • Ruby 的方法调用好像野马 at 2013年05月31日

    #28 楼 @iBachue "函数是第一公民"我还是觉得有。写 func.call() 和写 func.() 虽然都不及 func() 简洁,但我觉得不能说没有。

    PS. 你早把这个意图说出来我就可以少打点字了 - -

  • Ruby 的方法调用好像野马 at 2013年05月31日

    #23 楼 @iBachue 无法否认,这种情形下 Python 的写法打字更少。

    但是在现实的充分 OO 的代码中,使用协作者对象,要比使用从协作者对象身上"取下来"的已绑定的方法直观得多。更不要说取未绑定的方法,然后再伺机把未绑定方法所属的类的实例传进去调用 (你看用文字描述就这么费劲,更不要说后来人阅读代码时会有多大的认知障碍了).

    如果你确实面对着需要频繁使用方法对象的场景,那么我无可辩驳。对我来说,目前能迅速回想起来的,Ruby 的方案对我而言更优越的用例有这么两个:

    Getter API 演变。

    比如说我们有个 UserPresenter 类 (在 fat model 的风格下很可能会是 User 类), 需要提供 avatar 属性返回头像 URL. 习惯上会觉得"啊既然是返回个 URL 字符串那么就用属性 getter 好了". 接下来需求变更,avatar 可能会有需要多个不同的大小。之前所需的尺寸只是最常用的而已。对 Ruby 而言这个状况很容易解决:把 avatar 方法实现成多接受一个参数来制定尺寸即可。而反观 Python, 假如把属性 getter 换成方法,旧的代码都要逐个改掉。如果不换,就没法制定尺寸参数。这个问题在我现在面对的 codebase 里就真实地存在着。

    Stub

    写隔离测试时,stub 是个常用的解除依赖的手段。Python 对象想要做 stub, 就要考虑"这个要 stub 的东西的获取方式是属性还是方法?". 而且在面对这种情况时:

    class Foo(object):
        @property
        def bar(self):
            return 'bar'
    
    def test_foo(monkeypatch):
        foo = Foo()
        monkeypatch.setattr(foo, 'bar', 'bar')
        assert foo.bar == 'bar'
    

    monkeypatch.setattr(foo, 'bar', 'bar') 处会抛异常。虽说这种情形 stub 的方法也不是彻底没有,我正在用这个库. 但瞄了一眼具体实现,发现背后全是黑魔法。项目也不再维护了。用着多少有点担心。以及,这个库在 stub 时,所使用的预设返回值不能是 Mock 的实例。全是令人头疼的因素。而这些问题在 Ruby 的设计中根本不存在。

    以及可能还有更多例子,但一时也想不起来了。就写这么两个吧。

    不过,我依然无法下结论说 Python 和 Ruby 谁的方案更"好". 我只能说对于我个人的编程习惯和面对的问题领域而言,Ruby 的设计更适合我而已。

    EDIT: 忘了说,前面 Python 代码示例中的 monkeypatch 是来自 py.test 测试框架的一个自带的插件 (在 pytest 的术语中属于 fixture 插件): http://pytest.org/latest/monkeypatch.html

  • Ruby 的方法调用好像野马 at 2013年05月31日

    #19 楼 @iBachue 我不清楚你所说的“弱点”和“这方面”具体是指什么。所以我无话可说...

    #17 楼 的本意还是想告知 #7 楼, 方法(包括未绑定的和已绑定的)作为对象,作为一等公民(可以被传递,被返回,储存在局部变量/实例变量等储值机制里),是存在的。

  • Ruby 的方法调用好像野马 at 2013年05月30日

    只能说 LZ 的比喻有点没读懂。

    #9 楼 @fsword 我觉得还是有的:

    class Foo
      def bar
        puts 'bar'
      end
    end
    
    f = Foo.new
    f.method(:bar).call
    Foo.instance_method(:bar).bind(f).call
    
  • 看了 LZ 的编辑,那么我单就技术问题说说吧。做了一年左右的"职业" Python web 开发,觉得 LZ 提出的问题所考察的知识还是很重要的。如果这些知识还要在用的时候临时去查,多少有点对不起简历上的"有 Python 使用经验".

    一个例外是第 15 题,我个人目前还没有心情去扣流行的 web 开发框架底层的代码,因为现在的工作用的是个不怎么流行的...... 以及,流行的框架经由社区的打磨,一般也足够稳定,没出什么故障的话我反正很少去扣。话说回来,如果这方面的知识和 LZ 招的职位需求很契合 (比如需要为框架开发插件/自行 patch), 那么问问无妨。

    以及,我觉得还可以补充一下模块系统 (虽然不难) 和 new style class 的方法解析顺序什么的。这些在我看来也属于必须掌握,随时脑内取用,最好不要临时去查的知识。虽说工作时总归是有条件去查文档,但解决稍微复杂一些的问题 -- 尤其是 debug 别人的代码 -- 时,如果这些知识不能像蝙蝠侠腰带上的工具一样熟悉,估计是会有些吃力的。

    话又说回来,既然 LZ 对这种答题的形式也反感,完全可以换一种形式来考察这些知识点。比如这篇文章的作者采用的方法是:制造一个相对真实的简单问题,让面试者现场解决。问题本身要能覆盖若干面试官所关心的知识点 (可能覆盖不全,但可以再引导面试者重构,覆盖更多知识点的同时也考察重构能力), 也能观察得到面试者的工作方式。这样的形式估计就好很多。

  • 果然自己的代码写得有点冗余~ .to_i 本身就已经转换成整数了,再 .round 没有意义。只调用 .to_i 的话就可以像 #7 楼 那样利用 &to_i 的语法了。

    其实看了 #2 楼 的描述,我依然不能确定 lz 的原始需求是什么。如果能确定输入数据肯定都是干净的浮点数(只是暂时存成字符串),那么按 .to_i 的结果分组应该肯定是够用的。以及,如果数据是稀疏的,比如缺少 1.x 的输入,那么在输出的数组里原本属于 1.x 的位置上应该是 nil, 还是空数组,都只能看具体需求。

    #12 楼 @alsotang 既然你用了正则,那么我也引用一下自己学习正则的知识。这本书教会我的一个重要理念是:先熟悉你手头的数据,正则写得足够好即可,十分严谨的、面面俱到的 parser 用一个巨大的正则来做非常的痛苦。像 LZ 这个问题,如果已知数据都是存成了字符串的浮点数,确定有“浮点数”这个语义在的话,用 .to_i 我觉得非常合适。但如果真如 #2 楼 所言,每个元素只是“中间恰好有一个 . 的字符串”,那么用正则确实更合适。在背景信息完整之前,我觉得没法断言哪个方案更正确。我们写代码都是想解决问题,而不是为了让自己的答案反映出自己学会了课本上的知识点。

    依然,如果原始需求不明,数据来源不确定,output = [ a[0..2], a[3..4], ... ] 这个答案我觉得也未必不可。但是在社区里扔下这么一个答案就跑给人太 trolling 的感觉,所以我没敢这么做。

  • 能描述一下需求么?只看这个输入输出的话,我觉得可以这样

    a = ["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"]
    output = [
      a[0..2],
      a[3..4],
      a[5..6],
      a[7..7],
      a[8..9],
    ]
    

    假如需求是"按照每个元素的整数位分组", 那么可以这样

    a = ["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"]
    
    grouped = a.group_by {|n| n.to_i.round}
    output = grouped.values_at(*grouped.keys.sort) # => 应该就是你需要的.
    

    不过话说回来,直接拿 grouped 这个 hash 去用可能更方便?而且,假如说输入的数据中没有 1.x 的数,那么这个方法的输出可能会有问题。总之还是希望 LZ 完整严密地描述一下需求。否则我觉得还是前一个办法更好

  • 从 RVM 到 rbenv 失败 at 2013年05月25日

    不妨给 ruby-build 开个 issue 吧~

  • #33 楼 @zhenning 这个无法否认。Python 在这方面的积累明显胜过 Ruby。反过来,Ruby 在 Web 开发方面的积累也胜过 Python。这样比下去就等于在比社区的兴趣倾向与自己日常工作的契合程度。不过这种高度专业领域的编程问题反而容易做出决策,没有太多好纠结的。

    于是我写的这一系列 blog 只专注对比语言设计,如 #32 楼 所述:连标准库都懒得去写。

  • #28 楼 @bhuztez 说到 OpenStruct,Python 也是可以自己山寨一个的:

    class OS(object):
        # __eq__, __setitem__ 什么的也都可以实现得了。
        def __init__(self, **attrs):
            self.__dict__.update(attrs)
    

    恼人的是这么好用的东西竟然在 Python 标准库里就是没有。如果写二者的标准库的话我还可以至少再写一篇,FileUtils, OpenStruct, rake, Minitest, URI, Forwardable, Pathname, YAML 等等,以及 Core 里面的 Time 和 Struct,在 Python 那边要么干脆没有对应物,要么有但易用性完败。但想想绝大多数情况下开发者可以装第三方的包,只对比标准库的意义不那么大了。而且库的演进要容易得多,语言设计留下缺陷就是长期硬伤。

  • #30 楼 @bhuztez 发现 object 的直接子类的 __bases__ 不让改 - - 搜了一手发现有这么个问题:http://bugs.python.org/issue672115 如果自己额外定义个用来替代 object 的基类似乎可以做到,但这么搞又麻烦了 oTL

    #TIL

  • #27 楼 @bhuztez 啊没错,直接用已绑定的方法(bound method)也是一个制造 callable 属性的办法。但这又要求方法定义在当前对象的方法解析顺序中能找得到。如果方法定义在别处,恐怕又会受限。

    依然,虽然理论上可以做到,但因为种种实现门槛/细微的不舒适的存在,在现实世界的代码里就难得一见。比如我在生产环境还见过 Python 中实现 Ruby 的“重新打开一个类去添加 mixin”。具体的实现是:用 mixin 与旧类创建新的类,然后去修改旧类所在模块的作用域,把新类塞进去。结果代码稍显肮脏,更糟糕的是会因为旧类在 mixin 之前被别处 import 拿到引用(虽然利用了 Python 的 package 中 __init__.py 优先执行的逻辑但还是出了问题,诡异得很,至今原因不明),而导致新旧两个类并存使用。导致我现在的想法就是“有时间一定把那玩意重构掉”。当然实际上也一直没那个时间......

  • #23 楼 @bhuztez Yes and no. Python 虽然可以用“callable 属性”来模拟按实例多态 (per-instance polymorphism),但这个 callable 并不像常规的方法那样可以拿到 self 作为第一个参数。虽然我们还可以用实现了 __call__ 的类,或者闭包,以及动用 partial 模块等方式来让这个方法访问实例,但是有这样的实现门槛摆在面前,开发者往往习惯上就不会积极地去使用了。至少我很少见到。当然我个人阅历也实在有限。

    唔现在看来觉得确实应该把这一段加入到文章里去。并且也指出这种做法在 Python 社区并不多见。反观 Ruby 因为 eigenclass 的存在,统一地解决了类方法和按实例多态的问题,还提供了 extend 方法来简化使用。

  • #22 楼 @krazy 模块系统这方面在我看来有些争议。

    Python 的 import 更显式,而且每个模块有自己的作用域,可以不受外界干扰(EDIT: 按照下文所述,还是可能会受干扰,只是不到万不得已不会这么做)。而 Ruby 的模块系统借鉴自 Perl,所有文件共享一个作用域,相当于大家一起堆砌全局变量(虽然有良好的命名空间支持)。这样看来 Python +1.

    但是现实世界中,拿 Python 的模块标识符当作全局唯一标识,藉此访问/修改全局状态的用例也越发地多了起来。比如 [Mock] 模块的 patch 方法,就依赖这种访问方式,甚至随着调用方的 import 方式不同,patch 的使用还要多加小心。我还看到有生产环境的代码:模块本身提供了类似于 Rails 中的一组 model 对象,然后这个模块提供一个 init 函数来允许用户传入数据库和 memcache 的客户端,而这个配置逻辑也是依赖了模块标识符的全局性的。这样看来,Python 的模块系统反而是在制造不必要的复杂度。Ruby +1。

    所以既然有这样的争议,我就没有去写。只写了 Ruby 比较有把握完胜的 :)

  • #19 楼 @Tony612 哦这个... 当时考虑的是,如果用户有一些总是浮在桌面顶部的窗口(典型的如 IM),这些窗口往往都是在右侧。那么我的页面内容就占据左侧好了。

  • #8 楼 @Tony612 是故意的... 博客一共就这么点内容,还是觉得应该内容为重。

    而且我猜测以博客主要读者群体(程序员)的习惯,当页面上没什么可看的东西的时候应该会开始往没逛过的地方乱逛(也可能直接就关了页面了...),一眼看上去除了滚动到页面底端已经没什么别的去处了。这时底部导航大概还是能起到作用的(吧)。

  • #2 楼 @ugoa 收到。很多时候我都是觉得用英文表达更准确才故意用英文的 - -。混搭确实容易造成不必要的思维跳跃,会多注意。

  • 从 RVM 到 rbenv 失败 at 2013年05月25日

    假设你是用 ruby-build 编译的 Ruby,可以参考它的 wiki 来看看你遇到的问题是否有解决方案:https://github.com/sstephenson/ruby-build/wiki

  • 不知道 vim 行不行~

    vim * '+argdo setl fenc=utf-8' '+wall' '+qall'