原文参考: https://github.com/chinesehuazhou/python-whydo/blob/master/zh_CN/1-why-design-len()-and-not-x.len().md
为什么python求长度使用len作为内置函数,其他语言使用x.length()写法
主要有3个原因:
一. 将len设置为内置函数,可以直接读取底层的C结构体,速度快
Python 之禅: “实用胜于纯粹”
CPython会直接从C结构体读取对象长度,不会调用任何方法,而且获取长度是一个常见操作,如str,list,memoryview等类型上,操作必须高效, abs同理
Python 之禅:“不能让特例特殊到开始破坏既定规则。”
二. 前缀可读性更高,简单胜过复杂
三. 见名知意, len(x) 就是求长度的
作为新手友好型语言,内置方法起了很大作用
在python中:
str = "Hello World!"
print(len(str))
在Java中
String str = "Hello World!";
System.out.println(str.length());
Python 采用的是一种前缀表达式 ,而 Java 采用的则是后缀表达式 。
其他内置函数
int(s)
str(i)
类似于java的
Integer.parseInt(s);
String.valueOf(i);
Python 的内置函数不与特定的类绑定,它们是一级对象。而 Java 的“函数”则无法脱离类而存在,它们只是附属品。
没有绝对的好坏
python也有后缀表达式
mylist = [2, 1, 3, 5, 4]
mylist.sort()
print(mylist) # [1, 2, 3, 4, 5]
mylist.reverse()
print(mylist) # [1, 2, 3, 4, 5]
同时也有前缀表达式
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]
Python 之父 Guido van Rossum 曾经解释过这个问题( #TODO: add link),有两个原因:
对于某些操作,前缀符比后缀更好读——前缀(和中缀)表示法在数学中有着悠久的历史,其视觉效果有助于数学家思考问题。我们可以简单地把公式 x*(a + b) 重写成 xa + xb ,但同样的事,以原生的面向对象的方式实现,就比较笨拙。
当读到 len(x) 时,我就 知道 这是在求某对象的长度。它告诉我了两点:返回值是一个整数,参数是某种容器。但当读到 x.len() 时,我必须事先知道某种容器 x,它实现了一个接口,或者继承了一个拥有标准 len() 方法的类。我们经常会目睹到这种混乱:一个类并没有实现映射(mapping)接口,却拥有 get() 或 keys() 方法,或者某些非文件对象,却拥有一个 write() 方法。
优雅易懂是 Python 奉行的设计哲学 ,len() 函数的前缀表达方式是最好的体现。我想起 Guido 对“为什么索引从 0 开始 ”的解释。其最重要的原因,也正是 0-based 索引最优雅易懂。
出自《The History of Python: Why Python uses 0-based indexing》
让我们来先看看切片的用法。可能最常见的用法,就是“取前 n 位元素”或“从第i 位索引起,取后 n 位元素”(前一种用法,实际上是 i == 起始位的特殊用法)。如果这两种用法实现时可以不在表达式中出现难看的 +1 或 -1,那将会非常的优雅。
使用 0-based 的索引方式、半开区间切片和缺省匹配区间的话(Python最终采用这样的方式),上面两种情形的切片语法就变得非常漂亮:a[:n] 和 a[i:i+n],前者是 a[0:n] 的缩略写法。
面向对象的编程语言自发明时起,就想模拟我们生活于其中的现实世界。可是什么类啊、接口啊、对象啊、以及它们的方法啊,这些玩意的毒,有时候蒙蔽了我们去看见世界本质的眼睛。
桌子类有桌子类的求长度方法,椅子类有椅子类的求长度方法,无穷无尽,可现实真是如此么?求长度的方法就不能是一种独立存在的对象么?它之所以存在,是因为有“对象”存在,而不是因为有某个类才存在啊。
求某个对象的长度,这种操作独立于对象之外而存在,并不是该对象内部所有的一种属性或功能。从这个角度理解,我们能够明白,为什么 Python 要设计出内置函数? 内置函数其实是对世界本质的一种捕捉。
为什么 list.sort() 没有返回排序列表?
在性能很重要的情况下,仅仅为了排序而复制一份列表将是一种浪费。因此, list.sort() 对列表进行了适当的排序。为了提醒您这一事实,它不会返回已排序的列表。这样,当您需要排序的副本,但也需要保留未排序的版本时,就不会意外地覆盖列表。
如果要返回新列表,请使用内置 sorted() 函数。此函数从提供的可迭代列表中创建新列表,对其进行排序并返回。例如,下面是如何迭代遍历字典并按keys排序: