Python中关于len函数的用法与原理详解

一直不理解 Python 中为嘛有 len 这种函数存在
例如要获取字符串的长度
要使用:
len(‘ABC’)
实际上是调用的
‘ABC’.__ len __()
为嘛不直接像其他语言那样设计成调用’ABC’.len()???
请指教。
Python中关于len函数的用法与原理详解

28 回复

前两天刚有人水了一贴
https://www.v2ex.com/t/557286


len()是Python内置函数,用来返回对象的长度(元素个数)。它的原理是调用对象的__len__()方法。

基本用法:

# 字符串
s = "hello"
print(len(s))  # 输出: 5

# 列表
lst = [1, 2, 3, 4]
print(len(lst))  # 输出: 4

# 元组
tup = (1, 2, 3)
print(len(tup))  # 输出: 3

# 字典
d = {'a': 1, 'b': 2}
print(len(d))  # 输出: 2

# 集合
st = {1, 2, 3, 4}
print(len(st))  # 输出: 4

自定义类使用len():

class MyCollection:
    def __init__(self, items):
        self.items = items
    
    def __len__(self):
        return len(self.items)

# 使用示例
my_obj = MyCollection([1, 2, 3, 4, 5])
print(len(my_obj))  # 输出: 5

关键点:

  1. len()的时间复杂度通常是O(1),因为Python对象会维护长度信息
  2. 对于自定义类,必须实现__len__()方法才能使用len()
  3. 不能用于数字类型(int, float等)

简单说就是:len()调用的就是对象的__len__()方法。

因为对世界本质的洞察

  1. 一种选择而已,避免你拿到一个对象去猜它到底是 .len() .length() 还是 .size()
    2. 在 CPython 中 len() 对于内置类型会读取 ob_size 字段而不是调用 len 方法,更快

    具体参见 Fluent Python 英文版第 14 页


1. 你的 IDE 没有自动补全吗?
2. 更快??只要数据结构内部维护一个 size 字段, 怎么取都一样快吧, 都是访问对象字段而已

代码可以短一个字节

自动补全?你都不知道你一个函数传进来的会是什么类型,怎么自动补全?( type annotation 是 py3 才支持的,而且仅仅是个标记,也不是什么强验证)

无所谓吧,go 不也是内置函数

你怕是用的假的 IDE 吧

  1. 假如有人给一个对象自定义了一个方法叫 XXX.len()
    2. 上面这种情况,你不知道返回的数据类型会是什么,因为任何人都可以定义一个类似的接口,并给你返回一些让你意想不到的返回值。
    3. 这样看来 len(XXX)返回一个 int 是不是方便快捷

你怕是 java 写多了吧
def func1(a):
然后你告诉我 a 有没有 len()方法?神一般 ide 也猜不出来好吧

其实就是定一个标准

所谓的 magic 方法, 我理解就是定一个内部标准

只要支持取长度的, 开发人员默认加一个__len__, 调用的人比较方便, 不需要查到底是什么方法

你觉得在这个问题上用 python 内置的 len ()可以解决?

我有一个想法,就是作者的灵感来自操作符重载,如果把 len 看成一个操作符(内置关键字),或许你就可以理解了。

同意楼上,把 len 看作求一个对象长度的运算符,这样只要实现了__len__就相当于重载了这样一个求长度的运算符。不是函数的角度,而是运算符。

不好的设计,历史遗留问题,没有必要强行解释

没谁逼着用吧?我有的时候不喜欢用 str()也会用.str()
len()/str()/int()这样我觉得挺好的

就是一个标准,一个共识, 你 len()一个对象,一定会得到它长度。 大家都遵循这个共识,就不用去猜是 a.length、a.len 、还是 a.len(), a.length() 。 至于 IDE 能不能补全,不是设计语言的人会去考虑的东西。

如果不愿意遵循这个共识,python 也没拦着你去实现 a.length a.len a.len() a.length() 。

#12 可以啊
当大家都遵守这个标准的时候,len(a) 能保证能获取得到
不遵守的话才会去翻文档然后顺便骂一句不 pythonic

给一个返回值是确定的,如果返回值不确定,编译通不过的

有洁癖可以去用 Ruby ……

《流畅的 Python 》中文版在 12 页,说的好像有点道理:

你怎么保证它传给你的对象支持 len ?你又没有静态检查

那篇帖是我发的,没想到才几天就有人问。不过,这里的回复,相比起来,友善的、有理性的多些。(目前来看)

我感觉这个是个特别特别特别好的设计

并没有必要分清 size(), .length, .length() 这种结构啊。。。
如果你需要弄清一个有长度的东西,那就直接 len() 非常符合 py 本身的哲学。

从设计者的角度来看,可以类比做 sizeof 单目运算符,然后为了跟其他运算符的调用规范保持一致。

当然,这一设计是否比后缀形式更好就是另一个话题了。我个人认为后缀 /管道一类的设计减少了括号嵌套,语序符合实际执行顺序,有利于可读性;但是,你不能指着一门 1991 年发布的语言,问他的调用规范为什么没有学 1995 年的 Java 和,1995 年的 Ruby 和 1998 年的 C++。

这是 Python 哲学的一部分.不然就到处都是 getLength,setLength 了

回到顶部