内置函数是 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 索引最优雅易懂。

让我们来先看看切片的用法。可能最常见的用法,就是“取前 n 位元素”或“从第i 位索引起,取后 n 位元素”(前一种用法,实际上是 i == 起始位的特殊用法)。如果这两种用法实现时可以不在表达式中出现难看的 +1 或 -1,那将会非常的优雅。

使用 0-based 的索引方式、半开区间切片和缺省匹配区间的话(Python最终采用这样的方式),上面两种情形的切片语法就变得非常漂亮:a[:n] 和 a[i:i+n],前者是 a[0:n] 的缩略写法。

所以,我们能说 len(x) 击败 x.len() ,支撑它的是一种化繁为简、纯粹却深邃的设计思想。

面向对象的编程语言自发明时起,就想模拟我们生活于其中的现实世界。可是什么类啊、接口啊、对象啊、以及它们的方法啊,这些玩意的毒,有时候蒙蔽了我们去看见世界本质的眼睛。

桌子类有桌子类的求长度方法,椅子类有椅子类的求长度方法,无穷无尽,可现实真是如此么?求长度的方法就不能是一种独立存在的对象么?它之所以存在,是因为有“对象”存在,而不是因为有某个类才存在啊。

所以,我想说,len(x) 击败 x.len(),这还体现了 Python 对世界本质的洞察 。

求某个对象的长度,这种操作独立于对象之外而存在,并不是该对象内部所有的一种属性或功能。从这个角度理解,我们能够明白,为什么 Python 要设计出内置函数? 内置函数其实是对世界本质的一种捕捉。

这些见微知著的发现,足够使我们爱上这门语言了。人生苦短,我用 Python。

关联阅读:

len是不是python内置函数_len(x) 击败 x.len(),从内置函数看 Python 的设计思想-阿里云开发者社区...相关推荐

  1. hive 元数据 自定义_如何在Hive中创建自定义函数UDF及如何直接通过Impala的同步元数据重用UDF的jar文件-阿里云开发者社区...

    如何在Hive中创建自定义函数UDF及使用 如何在Impala中使用Hive的自定义函数 UDF函数开发 使用Intellij工具开发Hive的UDF函数,进行编译: 1.使用Intellij工具通过 ...

  2. python列表索引超出范围 等于啥_python如何解决IndexError:列表索引超出范围?-问答-阿里云开发者社区-阿里云...

    我正在尝试为ucf101数据集生成密集流,但我不断收到以下错误: 我尝试在第68行中将video_name.split('')[1]更改为video_name.split('')[0],已编译代码,但 ...

  3. 利用python爬取飞猪信息_Python---20行代码爬取斗鱼平台房间数据(下)-阿里云开发者社区...

    在上一篇中,已经详细的讲解了如何获取数据,接下来是深度处理数据,这里调用xlsxwriter库来制作Excel表格. 工具:Python3.6.5,Pycharm 1.模块介绍 XlsxWriter模 ...

  4. pg数据库生成随机时间_postgresql 时区与时间函数-阿里云开发者社区

    postgresql 时区与时间函数 rudygao 2016-02-03 1951浏览量 简介: --把时间戳转成epoch值 postgres=# select extract(epoch fro ...

  5. 杭州内推 | 阿里云开发者社区招聘计算机视觉算法工程师(2022年毕业生)

    合适的工作难找?最新的招聘信息也不知道? AI 求职为大家精选人工智能领域最新鲜的招聘信息,助你先人一步投递,快人一步入职! 阿里云 阿里巴巴集团拥有海量的图像/视频数据,强大的计算能力和巨大的市场空 ...

  6. python函数编写_python 函数编写条规-阿里云开发者社区

    函数具有独立性.也就是常说的不要有太强的耦合性.要让函数能够独立于外部的东西.参数和return语句就是实现这种独立性的最好方法. 尽量不要使用全局变量,这也是让函数具有低耦合度的方法.全局变量虽然进 ...

  7. python string模块安装_python String模块-阿里云开发者社区

    string成员常量: ascii_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ' ascii_lowercase  ...

  8. python与材料计算公式_《从问题到程序:用Python学编程和计算》——2.11 补充材料-阿里云开发者社区...

    本节书摘来自华章计算机<从问题到程序:用Python学编程和计算>一书中的第2章,第2.11节,作者 裘宗燕,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2 ...

  9. python 变量类型list_Python基础变量类型——List浅析-阿里云开发者社区

    Python使用list 一.list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示 ...

最新文章

  1. 2011年5月系统分析师考试­
  2. python socket代码_python入门之socket代码练习
  3. int i=i++;和i=++i;和i++
  4. Grub4Dos 安装Ubuntu 收藏
  5. 有重复元素的排列问题pascal题解
  6. mysql延迟关联为什么快_MySQL 覆盖索引与延迟关联详解
  7. python时间格式转换time模块
  8. JavaScript重难点解析5(对象高级、浏览器内核与事件循环模型(js异步机制))
  9. 一文入魂!聊透分布式系统一致性!
  10. [Android]Fragment生命周期
  11. Java集合框架使用总结
  12. 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明
  13. 第21章 java线程(1)-线程初步
  14. 智能判断图片中是否存在某物体_如果给猫披上象皮,神经网络将作何判断?
  15. Bootstrap学习之三:使用排版
  16. C++ 字符串 C#解析后 两个字符串无法连接
  17. instantclient19\12\11版本下载
  18. 2022年北京航空航天大学计算机考研复试分数线
  19. idea run with coverage异常
  20. 学习游戏开发,有哪些常识需要了解

热门文章

  1. Cglib动态代理-MethodInterceptor的简单使用(转载)
  2. C++与C#难以抉择
  3. 揭秘百家号提示视频重复,最新去视频重复解决方法 新媒体视频去重复,批量处理去重消重去水印去log...
  4. SQL教程——循环结构
  5. 大型企业为什么需要IT外包,甲方的工作职责是什么
  6. 关于GBDT算法、XGBoost算法的基本原理概述
  7. Docker添加镜像加速器的方法
  8. 微信小程序自适应方法
  9. 2018最新BAT python面试题
  10. 『津津乐道播客』#035. 签证和被拒签的那些事儿