原文: https://zhuanlan.zhihu.com/p/36210899
首先,我在 14 年开始接触 Py,当时还在学校学习数据结构和算法,它是我最好的伙伴,因为我当时买了一本 Py 宝典,我就算上课没听,我看书上的 sample 代码就看懂了老师上课说的内容,然后转换成老师要的 C 程序代码,就算课没听,但是我知道怎么抽象数据结构。
但是,我最近特别讨厌他,因为我工作中用到它,因为我工作中每天都在写不等长的 占位符,我且把 tab 的长度的 space 数和 space (1 byte char) 长度的 space 混为一谈,我真不知道是谁发明这么变态的语言。正如有一天我去吃麻辣烫,我点的“咪咪辣”,然后见一妹子跟她闺蜜指着招牌上写的辣度——“变态辣”说:你别要变态辣,我跟你没完,你要是点变态辣你就是变态所以你怎么吃都不觉得辣。
嗯,就这么变态,我也是这么 think (about Python) 的。 あー、すごく変態だ、俺もそう思った Yes, it is so hentai, I think so.
吾辈认为,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 解析器语法解析也不方便,他说如果有黑客能做到的话也欢迎建议。 (然而我看他是自己给自己挖了坑,自己跳进去之后发现早知道不设计缩进语法,现在好了,还跟大家说,有哪位黑客能解决告诉他吧)
我彻底无法理解 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:
C++ 的继承方式多种,是为了能在没有运行时、虚拟机的环境下依然能组合出多元化的对象继承结构(数据复用结构)。
但是 Python 刚好相反,它让你要么什么都暴露,要么什么都隐藏,不要跟我谈 getattr 和 setattr 之类的元类特性,你觉得我为了 protected 我每次用都做这些好玩吗?
多重继承本身就是个 deprecated 的做法,它会有钻石继承的问题,而且 Python 绝大多数书上都让新手去绕开这个坑,而不是语言级别去解决这个问题。就是语言不去解决问题而是把问题交给用户自行解决。
Java 支持匿名类,C++ 既支持匿名函数也支持匿名类。
就连我黑了上万遍的 PHP 都支持匿名函数(closure)和匿名类。
但是,我还是包容的,因为 Python 对象允许后天行为的学习(为实例增加方法和属性)。但是写起来不成体统也不直观。lambda 发明就变成残废,你以为每个人都是数学家吗写个短公式不能换行做递归计算?递归?我记得 Guido 在讨论递归的时候是听厌恶的,他说他的 Python 是杜绝递归,不做尾递归优化,虽然网上有人提出 tail_call_optimized 修饰器的解决方法。
无论怎么说,网友的想法是好的,用户能去这么容忍 Py 不去怎么样而自行解决问题,说明用户都是好心人。
Guido van Rossum 估计是一个患有天才病(阿斯伯格综合征)的病人。
这样的人人际交往困难。患者有与人交往的强烈意愿,却缺乏相应的技巧,所采取的交往方式刻板、生硬、程式化,更无法理解表情、眼色、肢体动作等非语言表达的信息。所以患者往往不受欢迎,也不能灵活地应对场景变化,难以融入群体,建立并维持良好的人际关系。
去反观一下 Zen of Python,去看看 pep8,无处不体现这些特征。
这就是我在标题用【掩耳盗铃】的原因,我认为 Guido 一直在做这种事情,他一味地崇拜 ABC,把开发者当傻逼,他以为他从语法上去强制洁癖了代码就把代码变得圣洁。
稍微熟悉点的开发者,甚至绕开 Python 这种机制去写出非常难调试的场景,比如利用 setattr 和 getattr 等来私藏很多“元”,就算外表调用光鲜,内部还不是一样晦涩,而且这样还非常难调。这样的类让人看起来“正直”,但是实际上是个犯罪系数很高的类,然而你从语法的简洁能看出来吗?根本看不出来。
正如很多很多销售都穿得很正装,他是魔鬼就要你去被他套圈子套路。你上当了但是你还认为他是个好好先生,好男人。
从限制语法来限制开发者的单一调用方式万金油式地解决问题就是个坑,你以为你是上帝一行代码解决所有问题,那你这一行代码得为了适应千万场景写多少天?
搞得像服务员小姐,就是抿个嘴都得先拿个东西挡一下,然后再去擦拭,那勺子吃饭要讲究礼仪抬起哪只手,否则会被老板(语法检查器、解释器编译时)批评(警告)甚至是处分(Error)。
你 tab space 那么多,给谁看,耽误了工期,你在字里行间的词汇中写出朵花来都没用。
函数逻辑没写对,doc string 写得再详细,那也是欺骗。
就算你 space tab 出了 全宇宙圣经级 pep8 代码,但是跑不起来,设计架构也不完整不成熟,实现效率低出品慢。那又有何用?
不过我倒是悟出了一个真相,一个道理:
Python 是写来装逼的(外观式编程)
相信 Python 在礼仪程序(Python 写的不是用来运行而是拿来作为礼物送人给别人看)讨好上司看自己写的代码多么礼仪还是很有价值的。
第一个观点:
然而我并不需要这种写了半天都没格式化好还有浪费时间在因为不提倡 if while 嵌套不能多行匿名函数我得绕各种弯子解决问题,浪费时间在代码风格上的语言。
第二个观点:
我需要的是,我写得舒服,看着清晰、正确,作为 adult 就应该自觉去格式化代码而不是被代码格式化暴力与强奸,应该是我写代码不是代码写我。
有时候为了写出符合 pep8 风格又要达到算法优化级又要完成任务,那简直是多烧脑,不如去写 Haskell Ocaml,但是王垠在《我为什么不再做 PL 人》是这么评价的:
第一段
有一些 PL 人喜欢推广他们认为高大上的语言,比如 Haskell,OCaml,Scala 等。这些语言在 PL 学术界很受尊重,所以他们以为这些语言能够奇迹般的解决实际的问题,然而事实却不是这样的。事实是,这些学术界出来的语言,其实缺乏处理现实问题的机制。为了能够在学术上证明程序的所谓“正确性”,而且由于类型系统本身的局限性,这些语言往往被设计得过于简单,具有过度的约束性,以至于表达能力欠缺。
最后,你发现用这些语言来写代码,总是这也不能做,那也不能做,因为你要是那么做了,编译器就无法发现“类型错误”。到最后你发现,这些语言的约束,其实是无需有的。如果放宽这些约束,其实可以更优雅,更简单的对问题进行建模。对正确性的过分关注,其实导致了 PL 人选择蹩脚的语言,写出绕着弯子,难以理解的代码。
第二段
这种天才病的危害在于,它蒙蔽了这些人的眼睛。他们不再能设计出让“普通人”可以容易使用的产品。如果你不会用,他们就会嘲笑你笨,而其实呢,是因为他们的设计不好。他们喜欢用含混晦涩的方式(所谓“函数式”)的写法来构造代码,让其它人阅读和修改都极其困难,……
关于 lambda 的讨论,我想引出来的是一门语言,要么提供匿名函数,要么提供匿名类:
C++
std::function func = [](type param) {
// code
}
用过 cocos2d-x 的人都知道绑定 event 最常用的方法就是它
JavaScript
function MyIterable { this.arr = [] }
MyIterable.prototype = Object.create(Object.prototype);
MyIterable.prototype.constructor = MyIterable;
MyIterable.prototype.iterWith(func) {
this.arr.forEach(function(item) {
func(item);
}
}
当然,这些东西放到抽象类作为等到子类去实现也是可以的:
PHP
abstract class MyIterable {
$arr = [];
public function iterWith() {
foreach($this->arr as $value) {
$this->iterWithImpl($this->arr);
}
}
abstract public function iterWithImpl($item);
}
$my_iter = new MyIterable {
public function iterWithImpl($item)
{
echo $item;
}
}
当然 PHP 也可以用 closure 匿名函数解决:
class MyIterable {
$arr = [];
public function iterWith($callback) {
foreach($this->arr as $value) {
$callback($value);
}
}
}
$my_iter = new MyIterable {
public function iterWithImpl($item)
{
echo $item;
}
}
以上说明 PHP 提供两种方案。
Java 的例子,跟 PHP 基本差不多,而且 Java 还可以用 Lambda 来便捷地创建匿名类(以下摘自安卓 button 监听):
public void myBtnClick() {
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"这是弹窗",Toast.LENGTH_SHORT).show();
}
});
}
What about Python?
Python 既没有匿名类,lambda 也是个残废
这样的语言,你说写起来能不绕?写起来绕就算了,但是宗教教条一样的语法限定又怎么说,那就完成一件事不仅仅要注意它的教条规范,还得去绕着弯来做事,这是多么的困难。
Python 教条主义符合以下特征:
@rocLv 的回复跟让我可笑,同时也正好符合