从内置函数看 Python 的设计思想:len(x) 是否击败 x.len(),

内置函数是 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() 函数的前缀表达方式是最好的体现。

让我们来先看看切片的用法。可能最常见的用法,就是“取前 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。

关联阅读:

Guido 解释 len 的由来: https://mail.python.org/pipermail/python-3000/2006-November/004643.html

Guido 解释 0 索引的由来: https://python-history.blogspot.com/2013/10/why-python-uses-0-based-indexing.html

本文章来源于网络,如有侵权请留言!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473319.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解密Redis持久化

本文内容来源于 Redis 作者博文,Redis 作者说,他看到的所有针对 Redis 的讨论中,对 Redis持久化的误解是最大的,于是他写了一篇长文来对 Redis 的持久化进行了系统性的论述。文章非常长,也很值得一看,NoSQL…

牛客 共鸣问题(思维难题)

文章目录1. 题目2. 解题1. 题目 链接:https://ac.nowcoder.com/acm/contest/10325/B 来源:牛客网 现在有n个音符和m对共鸣关系,编号为1~n, 每个音符自己有一个奏响时的优美程度, 共鸣关系(x,y,z)表示音符x和y同时奏响…

GitHub标星2.6万!Python算法新手入门大全

今天推荐一个Python学习的干货。 几个印度小哥,在GitHub上建了一个各种Python算法的新手入门大全,现在标星已经超过2.6万。这个项目主要包括两部分内容:一是各种算法的基本原理讲解,二是各种算法的代码实现。 传送门在此&#x…

Notepad++的json 格式化

一、在线安装: 1. 打开nodepad 2. 找到JSON Viewer 点击右上角"安装", 会有提示框安装重启notepad, 点击ok 3. 自动重启后, 就可以看到插件这栏有JSON Viewer了, 至于用哪个选项可以格式化, 就来动手试试吧~~~ 二、下载复制到指定位置 1、下载对应版本的…

Pytorch 张量tensor

文章目录1. tensor 张量2. 运算3. 切片、形状size()、改变形状view()4. item() 只能读取一个元素参考 http://pytorch123.com/1. tensor 张量 empty 不初始化 import torch x torch.empty(5,3) # 不初始化 print(x)tensor([[1.0010e-38, 4.2246e-39, 1.0286e-38],[1.0653e-3…

移动硬盘无法弹出的问题

1.运行任务资源管理器 2.结束explorer.exe 3.新建任务explorer.exe 4.弹出移动硬盘 转载于:https://www.cnblogs.com/wbbice/p/3800907.html

python中的有序字典及其使用方法

有序字典和通常字典类似,只是它可以记录元素插入其中的顺序,而一般字典是会以任意的顺序迭代的。 1、普通字典: d1{} d1[a]A d1[b]B d1[c]C d1[d]D #此时的d1 {a:A,b:B,c:C,d:D} for k,v in d1.items():print k,v 输出结果为:…

Pytorch 自动微分

参考 http://pytorch123.com/ Tensor.requires_grad True 记录对Tensor的所有操作,后序.backward() 自动计算所有梯度到 .grad 属性 import torch x torch.ones(2,2, requires_gradTrue) # 默认是False print(x)tensor([[1., 1.],[1., 1.]], requires_gradTrue)…

写了 10 年代码之后,我学到的 7 个绝对真理

明年就是我的开发者生涯的第十个年头。整整十年!我有三分之二的时间都用在了 Web 开发上。在孩童时代,当其他小孩还在学习乐器或芭蕾舞的时候,我在自己的卧室里用代码编织了一个神奇的世界。为了给这十年来一个总结,我想分享一下我…

1502: [NOI2005]月下柠檬树 - BZOJ

Description Input文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度)。第2行包含n1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度。第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的圆…

Pytorch 神经网络训练过程

文章目录1. 定义模型1.1 绘制模型1.2 模型参数2. 前向传播3. 反向传播4. 计算损失5. 更新参数6. 完整简洁代码参考 http://pytorch123.com/ 1. 定义模型 import torch import torch.nn as nn import torch.nn.functional as Fclass Net_model(nn.Module):def __init__(self):…

python3之批量修改文件名称

import osdef folder_rename_add():#1. 获取要重命名的文件夹 名字 (事先存在的)folder_name input("请输入要重命名的文件夹:")#2. 获取制定的文件夹中的所有 文件名字file_names os.listdir(folder_name)#3. 重命名for name in file_name…

开发人员:月薪过万与年薪百万之间的差距

有一句话在开发人员圈子广为流传:“初级开发人员的标志就是需要在中级和高级开发人员的指导下完成工作。”所以,我们不要苛刻初级开发人员写的代码对错严谨,毕竟每个开发人员都有这样的一个过程。据译者观察,初级开发人员往往认为…

天池 在线编程 所有子数组之和(排列组合)

文章目录1. 题目2. 解题2.1 暴力解2.1 O(n) 解1. 题目 给定一个数组nums, 你需要返回这个数组所有子数组之和。 如果nums [2, 4, 1], 数组所有的子集是 {[2], [4], [1], [2, 4], [4, 1], [2, 4, 1]} 保证返回的结果是int的类型 len(nums) < 50 示例 示例1: 输入: nums …

深入研究Python 世界的规则,我的薪资直接翻倍

前言 编程&#xff0c;其实和玩电子游戏有一些相似之处。你在玩不同游戏前&#xff0c;需要先学习每个游戏的不同规则&#xff0c;只有熟悉和灵活运用游戏规则&#xff0c;才更有可能在游戏中获胜。 而编程也是一样&#xff0c;不同编程语言同样有着不一样的“规则”。大到是…

MyEclipse中代码提醒功能

一&#xff1a;最近仔细研究了下spring mvc中的代码&#xff0c;自己在配置文件哪里来时出现问题&#xff0c;没有提醒&#xff0c;只好自己搜了下有关的信息。如下 window--->preferences---->java---->Editor------>Content Assist如下图&#xff1a; 讲画圈部分…

天池 在线编程 木材加工(二分查找)

文章目录1. 题目2. 解题1. 题目 有一些原木&#xff0c;现在想把这些木头切割成一些长度相同的小段木头&#xff0c;需要得到的小段的数目至少为 k。 当然&#xff0c;我们希望得到的小段越长越好&#xff0c;你需要计算能够得到的小段木头的最大长度。 木头长度的单位是厘米…

利用numpy删除DataFrame某一行/列、多行内容

一、用法&#xff1a; DataFrame.drop(labelsNone,axis0, indexNone, columnsNone, inplaceFalse) 参数说明&#xff1a; labels&#xff1a;就是要删除的行列的名字&#xff0c;用列表给定axis&#xff1a; 默认为0&#xff0c;指删除行&#xff0c;因此删除columns时要指定…

天池 在线编程 最频繁出现的子串(字符串哈希)

文章目录1. 题目2. 解题1. 题目 给定一个字符串&#xff0c;我们想知道满足以下两个条件的子串最多出现了多少次&#xff1a; 子串的长度在之间 [minLength, maxLength] 子串的字符种类不超过 maxUnique 写一个函数 getMaxOccurrences &#xff0c;其返回满足条件的子串最多出…

关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系

刚接触iOS开发的人难免会对苹果的各种证书、配置文件等不甚了解&#xff0c;可能你按照网上的教程一步一步的成功申请了真机调试&#xff0c;但是还是对其中的缘由一知半解。这篇文章就对Certificate、Provisioning Profile等做个总结。 1.概念介绍 如果你拥有一个开发者账户的…