• 对,而且因为人多,所以更容易一棒子打死其它编程语言,人口少些反而多样化

  • 我这里有两份 Siege 的运行结果:

    Intel 4 core:6090.13
    Apple M1 8 core:16000 (差不多这个数)
    

    以上完全能回复你 @badigege 的问题

    上面测试的 ruby 版本为 2.5.8,这个版本还没加 JIT,要是 2.6+,那就不用说了……

    另外,都 2021 了……有了 Apple m1 以后,我觉得大家就不要再提【性能】这个词抹黑 Ruby 了~

    有了 Apple m1 基本上别说 ruby,python 都能飞起来了……

    未来处理器还会继续加速的,所以主流脚本语言在 202x 以后大家都不用谈 performance,除非它真的 runtime 本身可能设计、源码 AST 啦 compiler 啦各方面啦真的就很差。

    Ruby 很好,请放心食用~

    老印象【慢】字就请题主忘掉它吧,谢谢惠顾~

  • 尝试使用 Ruby 3 调度器 at 2020年10月26日

    你说的是这个就是 各种 routine 常见 对 context 的上下文保存、切换

    如果直接调用系统 Thread 自然就不用这东西了

    对,没错,我们的理解都没错

    我想表达的不是说命题有问题,我想说的是某个场景(以我最后阅读过的 ruby src 2.3 作为理解基准):

    当你一个线程有多个 fiber,要多个 fiber 切来切去的时候,这时候还是用的一个核……

    所以你很聪明的说 io 不涉及计算来绕开了这个问题

    然后我想说的问题不是 io 的问题,而是计算的问题

    就是讨论的东西不太一样,我只是纯粹日常发表个人看法~

  • 尝试使用 Ruby 3 调度器 at 2020年10月17日

    事实上 Goroutine 的 Thread 并不是真正的 Thread 的封装并不能因为看起来暴露了一个类似 Thread 的接口,就认为这是 Thread

    我只是打个比方,但是用 pthread + 调度器 包装 其实也是一种似乎可行的方案,毕竟还是得开多个 thread 去 handle 这些 proc,不信你开多个 gofunc 对照着 mac 的任务管理器里面该 go 进程用了多少个线程就会发现了

    https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/edit

    https://golang.org/src/runtime/proc.go
    

    对于:

    只要你熟悉一下 Goroutine 的实现就会发现,其也是如 Fiber 的内部协作式调度,再和整体的 Thread 一起做出来的封装,是多线程多协程切换的实现。

    我确定它用的就是系统 thread

    // Create a new m. It will start off with a call to fn, or else the scheduler.
    
    // fn needs to be static and not a heap allocated closure.
    
    // May run with m.p==nil, so write barriers are not allowed.
    
    //
    
    // id is optional pre-allocated m ID. Omit by passing -1.
    
    //go:nowritebarrierrec
    
    func newm(fn func(), _p_ *p, id int64) {
    
        mp := allocm(_p_, fn, id)
    
        mp.nextp.set(_p_)
    
        mp.sigmask = initSigmask
    
        if gp := getg(); gp != nil && gp.m != nil && (gp.m.lockedExt != 0 || gp.m.incgo) && GOOS != "plan9" {
    
            // We're on a locked M or a thread that may have been
    
            // started by C. The kernel state of this thread may
    
            // be strange (the user may have locked it for that
    
            // purpose). We don't want to clone that into another
    
            // thread. Instead, ask a known-good thread to create
    
            // the thread for us.
    
            //
    
            // This is disabled on Plan 9. See golang.org/issue/22227.
    
            //
    
            // TODO: This may be unnecessary on Windows, which
    
            // doesn't model thread creation off fork.
    
            lock(&newmHandoff.lock)
    
            if newmHandoff.haveTemplateThread == 0 {
    
                throw("on a locked thread with no template thread")
    
            }
    
            mp.schedlink = newmHandoff.newm
    
            newmHandoff.newm.set(mp)
    
            if newmHandoff.waiting {
    
                newmHandoff.waiting = false
    
                notewakeup(&newmHandoff.wake)
    
            }
    
            unlock(&newmHandoff.lock)
    
            return
    
        }
    
        newm1(mp)
    
    }
    

    另外,libdispatch 也是一个多线程管理的 lib,为什么它不做 fiber 而是直接管理系统分配的 thread?

    puma 是多进程模型,但你有没有想过为啥 puma 一开始学 libdispatch 不写 pthread scheduler 而是使用 multi-process

    你的回答的意图和想法是对的

    我真正提出异议的是,我认为 多线程 / 进程 io 还是比单个 thread 单个进程,然后在单个进程线程来分时高效,因为你在单核利用到极致,也比不过多核心的使用。

    而且更何况是在 业务端的 web 场景,大量的业务充斥着不一定非常高效的业务调用和某些确实需要等待的场景,你的调度器就会无法使用,所以你提出了你说的这些是针对 I/O boundry 场景,但是我个人认为没有谁会闲着上班不写业务代码去写 server io 的 rw 方法。

    另外补充,java 的 netty / spring 好久之前就已经采用这种 selector worker handler 模型了,只是,或许你不喜欢用固定模型,你的想法或者憧憬的是那种用户 DIY 模式的 model 而不是那种固化的 SWH,就是什么时候调用随用户主义的

  • 尝试使用 Ruby 3 调度器 at 2020年10月17日

    非阻塞 是 阻塞 socket,跟异步没有半毛钱关系,上面丁丁小哥已经说了,其实他的回答应该对你描述和理解的挺有回答意义

    那么,异步指代的是什么?

    现代分时操作系统,让每个 process 轮流使用内核,后面细化了 process 之后,就允许 thread 轮流使用内核,一般情况下,你开多个 thread,开发客户端的同学应该都知道,app 会有个主线程负责渲染界面,如果你在主线程写了 sleep 100s,那就完了,你整个界面卡住 100s 动不了,这时候为什么客户端会有异步的概念,就是开一个新 thread 去做另外的事情,让界面渲染的 函数能跑而不是自己这个函数占着 thread 接下来要干的事情

    socket 阻塞,首先,读写本来就在你的 thread,不管是 main thread 部分的代码,还是 你自己的 thread 的代码,反正 read write 都会让这个线程做这个事情

    如果 connect 了网络的一个 addr 如果你调用 read(100),另外一边长时间都没给你发 100byte 的 string,那么你的 thread 就会一直卡在那等待

    这时候,有一种做法就是 multiplex,就是 select 这个 socket 有没有 readable 的 data,没有就不占用时间了,pass。

    我要加个重点:

    其实 ruby 的 IO.select() 已经封装了 iocp epoll 以及 kqueue

    所以,这些已经很简单了,我只是觉得博主可能有点夸大 Evt,其实 IO.select(...) 就可以了

    ruby 本质遇到的问题不是 IO performance 问题,作为 amber-kit 作者,我对 amber 开发感受到更多的是 ruby string 不支持 memcpy,而且 parsing decode encode 的效率较低,这些代码,你也会看到博主写的那个框架用了 c 来处理了这些部分的事情

    其实我一直想表达的是 ruby 并没有优化 string perfomance,streaming 处理的性能还是比 c / c++ / go / java 差些

    所以我一直在表达的意思是 过分强调 IO 优化,其实还不如优化一下基本类的算法性能

    还有的就是 ruby 3x3 视频我都看完了,老外当时讲的 Guild 类,为什么不能跨线程写,只能跨线程读,应该也是有考量的,当时我看完了 Guild 设计挺失望的。

    但是从业 go 之后,我明白了原来是 中国思维风格 趋向于喜欢把一些小玩意钻尖,就像 2020 年 10 月 16 日晚上 Apple 预订网站当时 App 都频频报错,估计是并发跟不上,你会不会蹦出这样的思维“为什么 taobao 就能做高秒杀呢”,其实 博主想要的那种就有点偏向于细化上处理的做法,可能趋向于喜欢把多核取消多线程绑定,然后用户自己的 fiber 和 scheduler 能手动利用。

    既然 把多核取消多线程绑定,然后用户自己的 fiber 和 scheduler 能手动利用,那 为何操作系统要发明 thread 和 process?

    顺便自己回答下面提出的问题“为什么 puma 使用多进程”,当然是我的个人观点,就是:简单

    老外应该更喜欢遵循现有的东西做实现,但是中国式思维,尤其 花为 喜欢刻意强调一些具有破坏性的东西作为一些可能更有逼格或者能力提现吧

  • 尝试使用 Ruby 3 调度器 at 2020年09月17日

    然后,我会告诉你,这种性能还是很低的,因为你只用了单线程,ruby thread 和 fiber 的关系是 thread 持有 fiber。

    就算不用文中提到的 fiber,也是可以利用【面向状态】来实现让 fiber 内部 handler 处理的时候实现 schedule。

    因此,fiber 跟并发还是扯不上关系,作者觉得并发了,是 set file descriptor flag non_block 了不让当前 thread 阻塞,好切入别的 subprocess。

    魔术师喜欢用障眼法来让观众感到真实和快乐

    amber 早就试过用这种模型,但是只是解决了编程风格问题,没有解决本质的 performance

    作者需要认清本质问题【利用多核】,要想利用多核,Thread 是需要的,有了 Thread 再把 fiber 加入 cpu time 抢夺我觉得多此一举,要是这样还不如学 go 封装一下 thread,说到这里,表达的意思明确了,fiber 早期设计不是去解决 io block。

    官方说明:

    Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM.

    对于并发,Thread 是需要的,但是 GIL 的出现,让 Thread 捆成了无法 Parallel,这时候真正 3x3 表达的的,正是 Guild,我不知道为何要提出 Fiber 3x3,估计是对 fiber 的迷恋。

    题主自己应该也发现,max performance 图也只有 8k qps,其实题主可能没意识到【这是单核的】,所以性能瓶颈其实不在 block nonblock,我建议博主试试一个 IO 往 另一个 IO write 1GB 的数据,你可以试试【阻塞 write】快,还是【非阻塞 write】快,你会得出更惊喜的答案。

  • Ruby 3 Fiber 变化前瞻 at 2020年09月17日

    thread 和 fiber 不存在取代、替代的说法,根据阅读源码可知,fiber 关联在 thread 下,另外你得看看 youtube 关于 3x3 guild 的设计,它的意图是线程 native 并发但是数据共享只读(为了安全)。

    fiber 的存在是为了实现一种调度式编码风格,但并不能真实实现并行,跟并行扯不上关系。所以 丁同学也说了,它的前瞻是实现调度 scheduler。

    其次,这个 scheduler 还要手工 consume & transfer。

    fiber1.transfer
    

    我个人认为,这种设计还是不够优雅的,比起 javascript 的 Promise,我个人认为 Promise 的 then then then 比这个手动写个 transfer 简单。

    someJob()
      .then(() => () {
      }).then...
    

    更不如 es 6 的 async await 好看...我就不写例子了

  • ruby 适合小而美的团队,不适合大团队协作,也不是不能协作,而是耗费的成本太高

    这句话同样用在 PHP Python

    最近公司用 Py 写的项目,我真的不想吐槽…… class 没写几个,全都是 dict 一个个拼的,随意 import,全都是 function(data) 式的编程你干嘛不回去用 C,然后 dict 你都不知道上下文是啥,因为它不是 class 没有固定的 attribute。

    Py 的对象还很另类,不 protected 然后 getattr setattr 作为属性寻找链很……

    Ruby 比起 getattr setattr 更倾向于 method_missing、send,而且区分开方法和属性

    Python 对于新学编程的人,是很简单,但是你用来写项目的时候,ORM、写几层封装你就知道什么叫蛋疼,注入麻烦而且死板,词法格式生硬。

    很多人说词法生硬的代码才好维护,屁!谁说的!

    本来可以通过 type_cast 顺势去递推逻辑的,显得很反射很 IoC 或是很 Design Pattern 的事情,Python 让你手足无措,只能老老实实写百行的 if else,层层嵌套多了拆成单个 function,function 写多了找得变态般的蛋疼。

    如果只让我写 if else 和 function,我宁可用 C 语言,因为至少同样的语法 C 性能比 Python 好,另外还有 Go lang,所以能写 py 不如写这俩货,我根本不知道现在 py 流行在哪儿,估计不过是 tensorflow 选择了它作为 wrapper language 吧。还有它确实不 OO 的话比其它语言要更容易入门。但真正要写 project 要维护要更可读更便捷还是要用点技巧的。

    Python 一句我撒手不管了我就让你什么都写不了只能写 if else 那就是好维护?

    Sorry I don't think so~

    阅读者看了一堆 py if else 之后可能还没进入主题

    function(self) 这个梗……

    lambda 只能一行写个短的

    很多语句因为太长,pep8 linter 一开逼着你换行之后,你会发现丑得很难看

    公司换用 go、python 或者说他俩流行我觉得最大原因是这俩货之前在上个十年没流行过,国内的技术选择是以资金为导向的,然后我觉得就是男的换个老婆,女的换个老公一样的事情。别人家的老婆 or 老公都是香的。

    而且以国人的口味,也就是看别家孩子有什么自己就像有什么吧,所以跟风,而且还很容易冷落一些不被关注的东西

    归根结底还是 因为你穿着不主流的东西在国内都是被歧视的。

  • Ruby 3 将有类型系统了 at 2019年04月29日

    我也是这么想的

    Swift 就有一套方法针对这个

  • 用 Go、Rust 都是爱好,当然 Go 解决了 C++ 的存在的问题,但是 Go 对于 micro controllers 不利呀,把 unsafe 列为禁忌的语言,你看哪个 bootloader 不是 ld 占据固定某片区的。

    如果谈爱好当然 including Ruby,其实很多项目如果有了 rb 根本就不需要 C 写得太多 code 了,而且更美观、简短和灵活,灵活我觉得是最重要的,这是能不能加速的重要条件,把 performance 交给 C,把 logic 交给 ruby。

    写代码,ruby 和 C 更配哦

  • 顺便路过

  • 看标题太吸引人了,所以进来冒个泡,撒西不理

  • Why Sometimes I Write WET Code at 2018年09月14日

    认可这个看法,我着手了一年多静态语言之后,虽然 eval / mm / reflect 很灵活,现在反过来就不再爱这些 EMR 了。

    如果是在小公司呆着,而且自己写项目,后者小团队,大家互相不干扰干活,是挺好的。

    如果碰到是华为、外包、要求严格的企业,他们就不让这么干了,因为他们崇尚 接口设计,而且也不允许使用灵活的语言。

    接口定义得良好,实现烂一点影响范围也有限,并且容易重构过来。

    不过对于 Python,我建议 @hooopo尤其是 Ruby、Python 这样动态语言,在没那么熟悉业务的情况下 删掉 Python,因为 Python 其实是一门很不灵活的语言。

    Python 的 private 根本不是大众口味的面向对象继承的,更像是 C++ 的 private 继承,到了后面的类没法好好取出来,只能通过 Parent_method,因此我觉得 Python 是怪味的,一开始就不旨意你去 call parent private。

    C++ 有 public 也有 protected 也有 private 继承模式,组合起来应对各种变态的场景,但是我觉得 Python 学到了它的坏处,同时在动态语言中多重继承。

    Python 这么做是为了让 object plain(扁平)得成个 dict,所有 object 都是 meta-table,而且还要是 C-flavor 的 map。

    怎么评价呢,反正个人的观点是认为 Python 就是模仿着强类型静态的模式和论调去进行动态编程,然而最终编码和行为一定是诡异的。

    所以 Python 的 object 让人用起来很刻板,写起来也感觉很死板。

    不像 Ruby,Ruby 从语法上光扬了 EMR,更偏向于 Java 真正将 object 当成有血有肉的 object 的 flavor。

    但是 Python 的刻板和死板好处就是对于数据结构初学者有好处,刚学计算机、编程的也很好接受基本类型,是字典就是字典,类就是个字典,对象也是个字典,数据结构就是 struct 套 struct,加上 Python 很少的语法糖,可以让新手很好入门。不用想太多。

    Ruby Java 适合进阶玩家,已经有了一套体系,在明白了基础之后,再去带有感性、抽象思维去使用才会好用。

    EMR 就是充斥了大量的 感性,就像人编码往往带有个性,这时候不是所有 team member 都理解自己的 imagination,这时候就会带来维护的困难,甚至自己也不记得当初 how to imagine this design 而维护困难。

    所以很多公司选择 Python 而不是 Ruby,也有这方面的原因。

    如果说:

    可读性 > 可扩展 > 优雅

    那么,Ruby EMR 之后产生了 DSL,是很优雅,很抽象,但是很可能别人是看不懂的,跟读唐诗文言文一样,得背负着可能无法读懂的框架的问题。DSL 赞扬了个性与隐晦,对于扩展与可读性也是不好下手的事情。

    作为企业,企业要尽可能考虑快速生产、迭代、编辑维护(Edit),在经济极端时刻必须极力消灭隐晦,宁可让你去写着从头到尾过程编程,连类(class)都不写,从一个又一个 file module import a import b 变量,跟 C 一样这里那里 extern,甚至干脆全局变量的无脑的 Python,也不会让你去 OOP,让你去 EMR,因为 EMR 是他们的大敌。

    所以 Ruby 是一门很可怜的语言,企业不敢用,尤其在现在霜月时刻(涉及敏感 ZZ 问题,不讨论)。

    同时,看到最近 Python 在拼命招人,感觉对编码越来越没兴趣了,感觉社会趋向变成了网站编辑、没智商的调包侠的世界了。

  • 小农思想害死人 at 2018年06月22日

    你想说我吗

  • 进程死锁 at 2018年06月10日

    哈哈哈哈哈哈哈哈

    你的浏览器提交死循环了

    还是说你重复点了很多次?

    表示 jruby 我只敢用 1.7 的…… 估计是兼容性问题

    jdk? openjdk? 6? 7? 8? 9?

  • 这一定是程序猿画的

  • 哈哈哈,“面向对象本身就快不起来”,嗯,怎么说吧,跟“面向对象”可能关系吧,个人觉得有点不太大(个人而已),Py Rb 的对象都是一块块有点体积的内存,相对于纯 C / C++ / Go writing 来说哈,我在 C / Cpp programming 的时候,ref 或 指针引用是高效的,其中 ref 是最高效的。 就拿字符串拷贝讨论,你从文件 read 一波数据,你的变量的内存得 copy 来 copy 去,C++ 的 vector 可以:

    auto data = new std::vector<char>();
    std::FILE* f = std::fopen("test.txt", "r");
    char * data_piece = new data_piece[4096];
    
    while (fin.eof()) {
        length = std::fread(& data_piece[0], sizeof(char), 1024, f);
        data.insert(data_piece, data_piece + length); // 重点在这一句
    }
    
    ...
    

    请不要吐槽这段代码,纯粹是随即编写的,就当作伪代码好了。

    C / C++ / Go 可以很好地重复利用一块内存其中的一部分,而且很好地自由地去利用它。因为反复内存分配(系统调用)是在 C++ 开发界普遍认为是很低效的。

    但是脚本语言让人遗忘了这些,反正 GC 会管理,写得痛快。

    所以之前就有人说,你要是用 JS 去处理 pack unpack 二进制,还得转 Array,总之就是不方便。

    另外,这也是当初我比较喜欢 ObjC 的原因,因为 ObjC 是面向对象的可半手动管理内存的语言,虽然 ObjC 有 ARC,但是很多场景你是可以高效利用内存的。

    要想在 AI 高效反复利用这些变量去进行快速而且高效的操作,那肯定还是这样的语言(C / C++)比较擅长。但是这还并不算最高效的,C / C++ 编译之后出来的机器码具体运算算法并不是最优的,有些大神喜欢用自己手工优化的汇编来将无法优化或编译器优化得不够极致但是需要效率的地方。

  • 吓得我赶紧把问题打勾了,免得更夸张的回复,有些时候只是为了陈述某种场景,很多时候没有遇见过的情况或者不同因人而异的想法,很容易引起别人另有想法。

    有时候网上很多新闻说的是父亲带着调皮的小孩因为闹眼子被打,父亲却露出笑容,然后结果一堆键盘侠的回复可能超出实际事件预期。

    有时候评论说说还好,但是别太认真。

    有时候他人不站在自己具体场合下去讨论具体情境,有时候说多了难免引起误会。

  • 谈谈我对 Python 的看法 at 2018年04月29日

    听到你的回复我已经安心了

  • 谈谈我对 Python 的看法 at 2018年04月29日

    你去看看是不是所有人都拿 jsonpath 来做这些的?你的前端给你传个 fomdata 你也去 jsonpath parsing 吗?

    另外,我们又不是审计局,我不做精算师,不是数据分析员

    做个小后端虽然只是增删改查,要不都把 matlab / R 也调进来 parse 一下某个 key value 吧,逼格更高一些

    要不我们别写代码了,让 AI 自动分析我们的代码 tab 缩进几个了然后自动化为业务 generate 代码吧

  • 谈谈我对 Python 的看法 at 2018年04月29日

    绕来绕去讨论好费劲……不想聊了,不回复了

    在最后最后,我举个极端的例子

    假如,你的 IDE 抽风了,把你的代码:

    if isinstance(result, list)
        if result == ...
          // code
    if isinstance(result, str)
        if result == ...
          if isinstance(result, int)
             if isinstance(result, int)
                if result == ...
                    // code
             if isinstance(result, int)
                 if result == ...
                     // code
    if isinstance(result, int)
        if result == ...
          // code
        ... 省略
    

    这样结构的,突然 IDE 一抽风,或者你不小心按 tab 加入了 shift 键盘,那么成了这样子:

    if isinstance(result, list)
    if result == ...
      // code
    if isinstance(result, str)
    if result == ...
      if isinstance(result, int)
         if isinstance(result, int)
            if result == ...
                // code
         if isinstance(result, int)
             if result == ...
                 // code
    if isinstance(result, int)
    if result == ...
      // code
    

    或者这样子:

    if isinstance(result, list)
    if result == ...
    // code
    if isinstance(result, str)
        if result == ...
    if isinstance(result, int)
    if isinstance(result, int)
        if result == ...
            // code
    if isinstance(result, int)
         if result == ...
             // code
    if isinstance(result, int)
            if result == ...
    // code
    

    或者这样子:

    if isinstance(result, list)
    if result == ...
    // code
    if isinstance(result, str)
    if result == ...
    if isinstance(result, int)
    if isinstance(result, int)
    if result == ...
    // code
    if isinstance(result, int)
    if result == ...
    // code
    if isinstance(result, int)
    if result == ...
    // code
    

    我这里是给了 // code 所以你看得出来,但是现实逻辑是残酷的……如果 IDE 还在抽风,你在撤销的时候并没有还原完整成了:

    if isinstance(result, list)
    if result == ...
    // code
    if isinstance(result, str)
        if result == ...
    if isinstance(result, int)
        if isinstance(result, int)
    if result == ...
            // code
        if isinstance(result, int)
        if result == ...
             // code
    if isinstance(result, int)
            if result == ...
    // code
    

    if 的先后顺序,逻辑都彻底不对了!

    当然大的变动可能性不大,小的有可能,比如你在 if 前面的空格不小心 backspace 错了,但是没察觉没在意,继续写代码,过后你发现逻辑出问题了

  • 谈谈我对 Python 的看法 at 2018年04月29日

    https://stackoverflow.com/questions/4043741/regexp-in-switch-statement

    Python 应该跟 PHP / Perl / Ruby / JavaScript 比,Java 不要拿进来说,Java 作为静态语言,天生编译时可以类型、行为直接检查完了,很多静态的优势,但是你要拿静态语言去跟脚本比灵活性没意义,所以 Python 应该跟 PHP / Perl / Ruby / JavaScript 比,但是比起 PHP / Perl / Ruby / JavaScript 没有任何优势,除了库比较大

    但是只要 Rubygems / npm 发展起来,我并不认为 Py 再有任何优势

    我觉得 Py 应该去接近 Ocaml / Haskell 去,因为大家没发现“普通人”用的语言都是 { },begin end,就 Python 拿 tab / space,就 Ocaml / Haskell 用各种函数式串式编程。总之就是 异类

  • 谈谈我对 Python 的看法 at 2018年04月29日

    无论怎么复杂,反正至少写起来顺手

    @lithium4010 说的:

    就是本来我可以简单描述的事物由于语言的限制我只能绕着说,这样就导致了不方便。

  • 谈谈我对 Python 的看法 at 2018年04月29日

    可以啊

    PHP

    $arr = ...
    switch($arr) {
        case 'test':
           // code
        case 123:
            // code
        default:
            if (is_array($arr)) { // code }
    }
    

    其实 Python 有办法解决,但是太恶心了

    网上给出了 filter / map 的方式,其实可以用 in 语法,但是那样 很绕

  • 谈谈我对 Python 的看法 at 2018年04月29日

    语法不一样的东西,不算等价吧。

    你总不能:

    result = [] # 假设 Array
    case result
    when Array
    when 'test'
    when 123
    else
    end
    

    这样的事情,你得:

    if isinstance(result, list) and ....
        code
    if isinstance(result, list) and ....
        code
    if isinstance(result, list) and ....
        code
    if isinstance(result, list) and ....
        code
    if isinstance(result, list) and ....
        code
    

    或者:

    if isinstance(result, list)
        if result == ...
          // code
    if isinstance(result, str)
        if result == ...
          // code
    if isinstance(result, int)
        if result == ...
          // code
    

    如果多个嵌套呢:

    if isinstance(result, list)
        if result == ...
          // code
    if isinstance(result, str)
        if result == ...
          // code
    if isinstance(result, int)
        if result == ...
          // code
    

    如果解析这样数据结构呢:

    result = {
        "name": "name"
        "aaa": {
            [{
                "address": {
                    "bbb": 
                      .....省略不想写啦
    

    解析起来这样的:

    if isinstance(result, dict)
        if 'name' in result and result['name'] == ...
           if ...
               if
                   if 以此类推
               // 啊咧,这是上一层吧?
         // 啊咧,这是上上层吗?(不是,这是上上上层)
    

    你说难看,可以这么说

    嗯,是的,这不仅难看,而且我都不记得 space 了几个,尤其我用了 tab_to_space,得很小心

    我知道 IDE 很智能,但是 IDE 也有抽风的时候,如果帮你多删了几个 space 的时候,你重新找位置是不是得感谢 IDE 全家呢?

    所以我才在文章表露我的意思,这说明 游标卡尺 在 Python 开发中是刚需品,必须得用到的

    每一位开发者得买一把 游标卡尺 放在抽屉避免异常情况,你一定用得上的!

  • 谈谈我对 Python 的看法 at 2018年04月29日

    嗯,你去看看 Py 有没有 switch 语句

  • 谈谈我对 Python 的看法 at 2018年04月29日

    好,那你怎么解决 switch

  • 谈谈我对 Python 的看法 at 2018年04月29日

    你把整个项目写完,然后几乎每个 input 都防御一下,跟 Overly 有什么区别

    先不讨论是否 Overly,再加上 Python 没有 switch 语句,你得写更多的 if

  • 谈谈我对 Python 的看法 at 2018年04月29日

    是的,抽成函数,所以这就回到了我上面说的:这样的话没必要的命名函数就很多了。

    真正的项目场合,你就是一大堆不打算公开的函数,怎么说呢,写起来就像是大学生刚学 C 语言,把功能拆散成一个文件里面 N 多个函数,不归类,如果时间赶也可能来不及整理。

  • 谈谈我对 Python 的看法 at 2018年04月29日

    我跟我同事说:防御式编程让我感觉太难受了

    祭出文章《编程过度防御?只有缺乏自信的程序员才会这样做》

    https://blog.csdn.net/csdnnews/article/details/79597639

    祭出书本《优雅的 Ruby》,里面有一章关于一开始就去这样防御让人看起来很恶心的讨论。

    另外,Python 很多时候写着防御式,有些我做的是 type casting,就是 a is b,写着写着,感觉还不如去用 Java C++,静态语言类型可以编译器检查,何必我这样手写着累。

    这就是我文中说的

    为何你不像 TypeScript 静态化?做事有头有尾,没必要文人面前扮演武人。