内容简介:内置函数是 Python 的一大特色,用极简的语法实现很多常用的操作。它们预先定义在内置命名空间中,开箱即用,所见即所得。Python 被公认是一种新手友好型的语言,这种说法能够成立,内置函数在其中起到了极关键的作用。
内置函数是 Python 的一大特色,用极简的语法实现很多常用的操作。
它们预先定义在内置命名空间中,开箱即用,所见即所得。Python 被公认是一种新手友好型的语言,这种说法能够成立,内置函数在其中起到了极关键的作用。
举个例子,求字符串 x 的长度,Python 的写法是 len(x) ,而且这种写法对列表、元组和字典等对象也同样适用,只需要传入对应的参数即可。len() 函数是共用的。
这是一种极简哲学的体现: Simple is better than complex。
但是,有些语言并不是这样,例如在 Java 中,字符串类有一个求长度的方法,其它类也有自己的求长度的方法,它们无法共用。每次使用时,通过类或实例来调用。
同样是求字符串长度,Python 的写法:
saying = "Hello world!" print(len(saying)) # 结果:12
而在 Java 中,写法可能如下(简化起见):
String saying = "Hello world!"; System.out.println(saying.length()); // 结果:12
Python 采用的是一种 前缀表达式 ,而 Java 采用的则是 后缀表达式 。
除了求长度,Python 的某些内置函数也能在 Java 中找到对应的表达。例如,数值型字符串 s 转化为整型数字,Python 可以用 int(s)
函数,而 Java 可以用 Integer.parseInt(s)
;整型数字转化为字符串,Python 可以用 str(i)
,而 Java 也有 String.valueOf(i)
。
Python 的内置函数不与特定的类绑定,它们是一级对象。而 Java 的“函数”则无法脱离类而存在,它们只是附属品。
从直观角度来看,Python 的表达似乎是更优的。但是,它们 并不具有可比性 ,因为这是两套语言系统,各有独特的范畴背景,并不能轻易地化约。
就好比是,不能因为拉丁字母笔画简单,就说它优于汉字,因为在表意时,字母(表音文字)是远逊于汉字(表意文字)的。同样的,日本借用了汉字的偏旁部首而造出来的文字,虽然更省笔墨,但是也完全丧失了意蕴。
以此类比,Python 的内置函数虽有简便之美,但却丢失了某些表意功能。有些人在质疑/抨击 Python 的时候,也喜欢拿这点说事,认为这是 Python 的设计缺陷。
这就引出本文最想讨论的一个问题来: 为什么 Python 要设计成 len(x) 这种前缀表达,而不是 x.len() 这样的后缀表达呢?
事实上,后缀设计也是可行的,以 Python 中列表的两个方法为例:
mylist = [2, 1, 3, 5, 4] mylist.sort() print(mylist) # [1, 2, 3, 4, 5] mylist.reverse() print(mylist) # [5, 4, 3, 2, 1]
它们都是通过列表对象来调用,并不是凭空从内置命名空间中拿来的。语义表达得也很清楚,就是对 mylist 做 排序 和逆转。
恰恰那么巧,它们还有两个同父异母的兄弟 sorted() 与 reversed(),这俩是前缀表达型。
mylist = [2, 1, 3, 5, 4] sort_list = sorted(mylist) print(sort_list) # [1, 2, 3, 4, 5] reverse_list = reversed(mylist) print(list(reverse_list)) # [4, 5, 3, 1, 2]
不同的写法,都在做同一件事(不考虑它们的副作用)。因此,后缀语法并非不可行,之所以不用,那肯定是刻意的设计。
回到前面的问题:为什么是 len(x) ,而不是 x.len(x),这根源于 Python 的什么设计思想呢?
Python 之父 Guido van Rossum 曾经解释过这个问题(链接见文末),有两个原因:
- 对于某些操作,前缀符比后缀更好读——前缀(和中缀)表示法在数学中有着悠久的历史,其视觉效果有助于数学家思考问题。我们可以简单地把公式
x*(a + b)
重写成x*a + x*b
,但同样的事,以原生的面向对象的方式实现,就比较笨拙。 - 当读到 len(x) 时,我就 知道 这是在求某对象的长度。它告诉我了两点:返回值是一个整数,参数是某种容器。但当读到 x.len() 时,我必须事先知道某种容器 x,它实现了一个接口,或者继承了一个拥有标准 len() 方法的类。我们经常会目睹到这种混乱:一个类并没有实现映射(mapping)接口,却拥有 get() 或 keys() 方法,或者某些非文件对象,却拥有一个 write() 方法。
解释完这两个原因之后,Guido 还总结成一句话说:“I see 'len' as a built-in operation ”。这已经不仅是在说 len() 更可读易懂了,而完全是在拔高 len() 的地位。
这就好比说,分数 ½ 中的横线是数学中的一个“内置”表达式,并不需要再实现什么接口之类的,它自身已经表明了“ 某数除以某数 ”的意思。不同类型的数(整数、浮点数、有理数、无理数...)共用同一个操作符,不必为每类数据实现一种求分数的操作。
优雅易懂是 Python 奉行的设计哲学,len() 函数的前缀表达方式是最好的体现。我想起在《 超强汇总:学习Python列表,只需这篇文章就够了 》这篇文章中,曾引述过 Guido 对“ 为什么索引从 0 开始 ”的解释。其最重要的原因,也正是 0-based 索引最优雅易懂。
使用 0-based 的索引方式、半开区间切片和缺省匹配区间的话(Python最终采用这样的方式),上面两种情形的切片语法就变得非常漂亮:a[:n] 和 a[i:i+n],前者是 a[0:n] 的缩略写法。
所以,我们能说 len(x) 击败 x.len() ,支撑它的是一种化繁为简、纯粹却深邃的设计思想。
面向对象的编程语言自发明时起,就想模拟我们生活于其中的现实世界。可是什么类啊、接口啊、对象啊、以及它们的方法啊,这些玩意的毒,有时候蒙蔽了我们去看见世界本质的眼睛。
桌子类有桌子类的求长度方法,椅子类有椅子类的求长度方法,无穷无尽,可现实真是如此么?求长度的方法就不能是一种独立存在的对象么?它之所以存在,是因为有“对象”存在,而不是因为有某个类才存在啊。
所以,我想说,len(x) 击败 x.len(),这还体现了 Python 对世界本质的洞察 。
求某个对象的长度,这种操作独立于对象之外而存在,并不是该对象内部所有的一种属性或功能。从这个角度理解,我们能够明白, 为什么 Python 要设计出内置函数? 内置函数其实是对世界本质的一种捕捉。
这些见微知著的发现,足够使我们爱上这门语言了。人生苦短,我用 Python。
关联阅读:
Guido 解释 len 的由来: http://suo.im/4ImAEo
Guido 解释 0 索引的由来: http://suo.im/5cr12S
本文原创并首发于公众号【 Python猫 】,未经授权,请勿转载。
原文地址: https://mp.weixin.qq.com/s/pK...
公众号【 Python猫 】, 本号连载优质的系列文章,有喵星哲学猫系列、Python进阶系列、好书推荐系列、技术写作、优质英文推荐与翻译等等,欢迎关注哦。后台回复“ 爱学习 ”,免费获得一份学习大礼包。
以上所述就是小编给大家介绍的《len(x) 击败 x.len(),从内置函数看 Python 的设计思想》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 算法学习:常用设计思想
- flex设计思想和语法简介
- 16 种设计思想 – Design for failure
- 设计开发中要避免的两个坑和一种可借鉴的设计思想
- 宜信开源|Wormhole 大数据流式处理平台之设计思想
- 彻底理解OkHttp - OkHttp 源码解析及OkHttp的设计思想
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人人都是产品经理——写给产品新人
苏杰 / 电子工业出版社 / 2017-6 / 66.60
《人人都是产品经理——写给产品新人》为经典畅销书《人人都是产品经理》的内容升级版本,和《人人都是产品经理2.0——写给泛产品经理》相当于上下册的关系。对于大量成长起来的优秀互联网产品经理、众多想投身产品工作的其他岗位从业者,以及更多有志从事这一职业的学生而言,这《人人都是产品经理——写给产品新人》曾是他们记忆深刻的启蒙读物、思想基石和行动手册。作者以分享经历与体会为出发点,以“朋友间聊聊如何做产品......一起来看看 《人人都是产品经理——写给产品新人》 这本书的介绍吧!