谈谈我对 Python 的看法

谈谈我对 Python 的看法

引言

首先,我在 14 年开始接触 Py,当时还在学校学习数据结构和算法,它是我最好的伙伴,因为我当时买了一本 Py 宝典,我就算上课没听,我看书上的 sample 代码就看懂了老师上课说的内容,然后转换成老师要的 C 程序代码,就算课没听,但是我知道怎么抽象数据结构。

但是,我最近特别讨厌他,因为我工作中用到它,因为我工作中每天都在写不等长的 占位符,我且把 tab 的长度的 space 数和 space (1 byte char) 长度的 space 混为一谈,我真不知道是谁发明这么变态的语言。正如有一天我去吃麻辣烫,我点的“咪咪辣”,然后见一妹子跟她闺蜜指着招牌上写的辣度——“变态辣”说:你别要变态辣,我跟你没完,你要是点变态辣你就是变态所以你怎么吃都不觉得辣。

嗯,就这么变态,我也是这么 think (about Python) 的。
あー、すごく変態だ、俺もそう思った
Yes, it is so hentai, I think so.

Python 的好处在哪里

吾辈认为,Python 不亚于就是让你不需要学复杂的数据抽象,就算你没有系统设计能力(尤其没接触过编程刚学的大学生),初学者一般教学入门计算机的认知就是输入输出,然后他们作为初学就真的只需要会用几个变量、一些条件语句、一些基础数据结构(数组、字典)来完成任务或应用程序开发。

你要是跟他们谈物件导向编程(OOP),他们是一脸懵逼的,而且,OOP 的思想是“世界的粒度就是对象,然后每个对象都是一个可复用可继承的数据结构,可派生甚至可有后天行为”,这些东西其实新手真的用不到或者对他们来说,他们不去实施稍微有规模的程序,应该说,他们也没有项目可做,尤其在学校的环境里,不可能给他们一个人去搞一个什么项目烧时间旷课来完成。

所以 Python 对他们来说也是很好的,入门者需要的就是简单的工具,过程化逐步深入学习。而不是一下子来个 Java,泛型、类型擦除、反射都糊他们一脸。

我为什么不喜欢它

你为什么要以缩进来作为代码块的基准

自从我历经多门语言,修炼多门技术甚至自己对词法有了解后。至今我在商业项目上终于又拿 Python 来做项目的时候,我反应过来,是谁告诉你拿占位符形成的缩进来作为一个代码块的基准的?

吾辈认为,虽然这个风格的语言,你不推广,自己用可以,但你别跑出来祸害大众让大众跟你一起这样呀。

内嵌问题

if condition:
    if condition:
        if condition:
            if condition:
    // code
        if condition:
            // code
            // code
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            if condition:
                ... 很长一段
                ... 很长一段
                ... 很长一段
                ... 很长一段
        if condition:
    // 啊咧?这是哪一个 if 的子块里面呀?

匿名函数问题

我不得不吐槽 Python 不能创建正常的匿名函数,Lambda 只能短写:
lambda x: //code

对于这个问题,Guido 说暂时没办法解决,因为缩进已经限制了语法的结构,如果 lambda 这么做,换行看起来怪怪的,而且如果加上的话 Python 解析器语法解析也不方便,他说如果有黑客能做到的话也欢迎建议。
(然而我看他是自己给自己挖了坑,自己跳进去之后发现早知道不设计缩进语法,现在好了,还跟大家说,有哪位黑客能解决告诉他吧)

所谓的 Zen of Python

我彻底无法理解 Python 的 “禅”:

首先,我写代码的时候开了 pylint,然后,我有一行代码这样的:

def method(param={}):

这时候 Pylint 给我警告,告诉我 {} 作为代码风格中间需要有个空格,好,我改成这样的:

def method(param={ }):

这时候 Pylint 给我警告,告诉我 { } 作为参数不能有空格

请问,你想让我怎样?反正怎么写里外不是人。

还有一堆我真不想说,比如每个类、方法都要我去写 doc string,否则红点点(警告信息)跟你没完。

而且还有类跟类定义之间换行两行

包空间中方法与方法之间换行两行

噢,这些强迫症,就是 Python 之禅!

我后来换成了 flake8,终于强迫症少了一些,但是我还是没法容忍:

my_data = ["Name 1", "Name 2" ...]
true_names = [ ... ]
if condition:
    if condition:
        if condition:
            my_data = [v for v in my_data if true_names] # 警告

警告行会有提示:代码长度超过 80 charactors,噢呀,我忘了空格占位符缩进也算在 charactors 里面呀,这样的话,如果缩进到 6 层,是不是根本没法写语句了。(示例只是 if,但是有可能是类定义完了里面有方法,方法里面有 while 还有 if 的常见案例,并不算过分)

写作很痛苦

def method(user_name, id_type, address, local_ip, host_name)
# Too long

这样写会太长而告警,换行了一下:

def method(user_name,
    id_type,
    address,
    local_ip,
    host_name)
# Warning

这样还是告警,提示是换行的话,第二个参数要跟第一个参数的首字母对齐,得这么写:

def method(user_name,
           id_type,
           address,
           local_ip,
           host_name)

警告终于消失,但是,我知道我空了几个空格吗?不知道,有时候我真的得祭出 Python 最佳编程实践专用神器—— 游标卡尺 来量一下我需要空几个格,然后下一行别急着继续空格,最好把上面的空格复制粘贴到下面,或者最好是把第三行开始删掉空格回到上一行右边,然后回车, 编辑器、IDE 自动换行,然后应该会自动 对齐到上一行开始。

另外,Python 不支持 switch 语句,很多场景没办法,只能多写几个 if,然后,如果具体值在一个集合里面,你可以用 dict 存一些值,然后 if in,但是,如果具体 case 不在一个集合里面,而是别的场合,那么你只能这么写:

if condition:

if condition:

if condition:

Python 不尊重高级开发者

继承没有 protected

C++ 的继承方式多种,是为了能在没有运行时、虚拟机的环境下依然能组合出多元化的对象继承结构(数据复用结构)。

但是 Python 刚好相反,它让你要么什么都暴露,要么什么都隐藏,不要跟我谈 getattrsetattr 之类的元类特性,你觉得我为了 protected 我每次用都做这些好玩吗?

使用已经公认差评的多重继承

多重继承本身就是个 deprecated 的做法,它会有钻石继承的问题,而且 Python 绝大多数书上都让新手去绕开这个坑,而不是语言级别去解决这个问题。就是语言不去解决问题而是把问题交给用户自行解决。

还是刚才说的 lambda 问题

Java 支持匿名类,C++ 既支持匿名函数也支持匿名类。

就连我黑了上万遍的 PHP 都支持匿名函数(closure)和匿名类。

但是,我还是包容的,因为 Python 对象允许后天行为的学习(为实例增加方法和属性)。但是写起来不成体统也不直观。lambda 发明就变成残废,你以为每个人都是数学家吗写个短公式不能换行做递归计算?递归?我记得 Guido 在讨论递归的时候是听厌恶的,他说他的 Python 是杜绝递归,不做尾递归优化,虽然网上有人提出 tailcalloptimized 修饰器的解决方法。

无论怎么说,网友的想法是好的,用户能去这么容忍 Py 不去怎么样而自行解决问题,说明用户都是好心人。

我要开始怼喽

Guido van Rossum 估计是一个患有天才病(阿斯伯格综合征)的病人。

这样的人人际交往困难。患者有与人交往的强烈意愿,却缺乏相应的技巧,所采取的交往方式刻板、生硬、程式化,更无法理解表情、眼色、肢体动作等非语言表达的信息。所以患者往往不受欢迎,也不能灵活地应对场景变化,难以融入群体,建立并维持良好的人际关系。

去反观一下 Zen of Python,去看看 pep8,无处不体现这些特征。

The Zend of Python

  • Python 自以为自己用着很优雅的,自认为优美,实际上在强迫用户去把代码辛苦地浪费时间格式化来显得很标致。
  • Python 自以为自己用着很明了的表达,实际上逼迫着用户有且只能用有限的表达方式和实现来完成任务。
  • Python 自以为的简洁去面对 Java 的复杂 PHP / Perl 的杂乱,实际上实现真正能模拟接近复杂业务的时候 if if if if 都不如 Java 一个 reflection / annotation 来得紧要,不如比 PHP / Perl 的 $obj->{$requestmethod} 来的及时。
  • Python 自认为的扁平不如 JS Promise / JxJava / Ruby Fiber 也有而且还可以带上长的、真正能发挥作用的匿名函数的非嵌套。
  • Python 自认为的间隔是在按捺代码编写者的耐心。
  • Python 自以为的可读性是牺牲编写容易性,甚至代码编写效率,影响开发者耐心,影响项目质量和进度。
  • 所谓的“规则至高无上”,是建立在里外不是人的变态苛刻编写制度之上。
  • 不要包容所有错误,为何你不像 TypeScript 静态化?做事有头有尾,没必要文人面前扮演武人。
  • 存在多种可能,不是尝试去猜的机会都没有,为了所谓的简化去用所谓唯一一种明显的万金油方案,然而,万金油程序往往是被有经验的开发者忌讳的。
  • Python 之父不是神,是个听不懂人话只会 ABC 的智障(当初就是为了开发 ABC 顺便发明 Python 的)
  • 不假思索就动手还不如不做说明你没听说过热闹驱动开发,不过吾辈认为 Python 就是现在热闹驱动开发炒出来的火,都没验证这门语言是不是 SB 就已经开始火了
  • 无法向人描述你的方案是不是好方案不是谁说了算的,请不要过于自我强调
  • 命名空间是一种绝妙的理念,我们应当多加利用,嗯,是的,但是相信 Python 开发者会把它 import somepkg.vara 来用,尤其 Python 大名鼎鼎的框架 flask,是这么用的:from flask import Flask,但是 app = Flask(name) 之后,app 就形成了耦合,app.db app.logger 等,我的意思是如果外部 from app import app.db 之后,如果其它模块需要引用或者那些模块再反向引用回 app 会出现惊喜(比如 controller 引用 db db 引用 app app 引用 controller),这跟 C extern var 一样的,全局变量、外部变量这种东西,你觉得这是好的编程方式?你就不怕被 OOP style 那群人黑一番?


这就是我在标题用【掩耳盗铃】的原因,我认为 Guido 一直在做这种事情,他一味地崇拜 ABC,把开发者当傻逼,他以为他从语法上去强制洁癖了代码就把代码变得圣洁。


稍微熟悉点的开发者,甚至绕开 Python 这种机制去写出非常难调试的场景,比如利用 __setattr__ 和 __getattr__ 等来私藏很多“元”,就算外表调用光鲜,内部还不是一样晦涩,而且这样还非常难调。这样的类让人看起来“正直”,但是实际上是个犯罪系数很高的类,然而你从语法的简洁能看出来吗?根本看不出来。


正如很多很多销售都穿得很正装,他是魔鬼就要你去被他套圈子套路。你上当了但是你还认为他是个好好先生,好男人。


从限制语法来限制开发者的单一调用方式万金油式地解决问题就是个坑,你以为你是上帝一行代码解决所有问题,那你这一行代码得为了适应千万场景写多少天?


搞得像服务员小姐,就是抿个嘴都得先拿个东西挡一下,然后再去擦拭,那勺子吃饭要讲究礼仪抬起哪只手,否则会被老板(语法检查器、解释器编译时)批评(警告)甚至是处分(Error)。


工具是拿来用的,不是拿来看的

你 tab space 那么多,给谁看,耽误了工期,你在字里行间的词汇中写出朵花来都没用。

函数逻辑没写对,doc string 写得再详细,那也是欺骗。

就算你 space tab 出了 全宇宙圣经级 pep8 代码,但是跑不起来,设计架构也不完整不成熟,实现效率低出品慢。那又有何用?


不过我倒是悟出了一个真相,一个道理:

Python 是写来装逼的(外观式编程)


相信 Python 在礼仪程序(Python 写的不是用来运行而是拿来作为礼物送人给别人看,讨好上司看自己写的代码多么礼仪还是很有价值的)


然而我并不需要这种写了半天都没格式化好还有浪费时间在因为不提倡 if while 嵌套不能多行匿名函数我得绕各种弯子解决问题,浪费时间在代码风格上的语言。

我需要的是,我写得舒服,看着清晰、正确,作为 adult 就应该自觉去格式化代码而不是被代码格式化暴力与强奸,应该是我写代码不是代码写我。
编辑于 2018-04-28