fue*_*sjr 196 python oop methods function string-length
我知道python有一个len()用于确定字符串大小的函数,但我想知道为什么它不是字符串对象的方法.
好吧,我意识到我很尴尬.__len__()实际上是一个字符串对象的方法.使用字符串对象上的len函数在Python中看到面向对象的代码似乎很奇怪.此外,__len__将名称视为名称而不仅仅是len 也是奇怪的.
Jon*_*nan 171
字符串确实有一个长度方法: __len__()
Python中的协议是在具有长度的对象上实现此方法,并使用内置len()函数为您调用它,类似于您实现__iter__()和使用内置iter()函数的方式(或者使用后面的方法)对于可迭代的对象,你的场景.
有关更多信息,请参阅模拟容器类型.
以下是关于Python协议主题的很好的阅读:Python和最小惊讶原则
Fed*_*oni 87
吉姆对这个问题的回答可能有所帮助; 我把它复制在这里.引用Guido van Rossum:
首先,为了HCI的原因,我选择了len(x)而不是x.len()(def __len __()来得晚了).实际上有两个相互交织的原因,都是人机交互:
(a)对于某些操作,前缀表示法只比读后缀更好 - 前缀(和中缀!)操作在数学中有悠久的传统,它喜欢视觉效果帮助数学家思考问题的符号.比较我们将x*(a + b)等公式重写为x a + x b的简单性,以及使用原始OO表示法做同样事情的笨拙.
(b)当我阅读len(x)代码时,我知道它是在询问某些东西的长度.这告诉我两件事:结果是一个整数,参数是某种容器.相反,当我读取x.len()时,我必须知道x是某种实现接口的容器,或者是从具有标准len()的类继承的.当没有实现映射的类具有get()或keys()方法,或者不是文件的类具有write()方法时,见证我们偶尔会遇到的混淆.
用另一种方式说同样的事情,我认为'len'是一种内置操作.我不想失去那个./ ...... /
unm*_*ted 37
有一种len方法:
>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>
Run Code Online (Sandbox Code Playgroud)
Luc*_*lho 31
Python是一种务实的编程语言,并为原因len()是一个功能,而不是一个方法str,list,dict等务实.
的len()内置函数直接与优惠内建类型:CPython的执行len()实际返回的值ob_size字段中PyVarObject的C结构代表任意可变大小的内置存储器中的对象.这是很多比调用一个方法快-无属性的查找需要发生.获取集合中的项目数是一种常见的操作,必须对这些基本类型多样为提高工作效率str,list,array.array等.
但是,为了提高一致性,在应用于len(o)用户定义的类型时,Python会将其o.__len__()称为回退. __len__,__abs__以及Python数据模型中记录的所有其他特殊方法可以轻松创建与内置函数类似的对象,从而实现我们称之为"Pythonic"的富有表现力且高度一致的API.
通过实现特殊方法,您的对象可以支持迭代,重载中缀运算符,管理with块中的上下文等.您可以将数据模型视为一种使用Python语言本身作为框架的方式,您可以无缝地集成您创建的对象.
第二个原因,由Guido van Rossum引用的支持就像这样,它len(s)比阅读和写作更容易s.len().
符号len(s)与带有前缀表示法的一元运算符一致,如abs(n).len()使用的方式比经常使用abs(),并且它应该像编写一样容易.
可能还有一个历史原因:在Python之前的ABC语言中(并且在其设计中非常有影响力),有一个一元运算符被编写为#s意味着len(s).
Ale*_*try 12
met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.
Run Code Online (Sandbox Code Playgroud)
这里的其余答案中缺少一些内容:该len函数检查该__len__方法是否返回一个非负数int。事实上,它len是一个函数,这意味着类不能重写此行为来避免检查。因此,len(obj)提供了无法达到的安全级别obj.len()。
例子:
>>> class A:
... def __len__(self):
... return 'foo'
...
>>> len(A())
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
len(A())
TypeError: 'str' object cannot be interpreted as an integer
>>> class B:
... def __len__(self):
... return -1
...
>>> len(B())
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
len(B())
ValueError: __len__() should return >= 0
Run Code Online (Sandbox Code Playgroud)
当然,可以通过将len函数重新分配为全局变量来“覆盖”该函数,但这样做的代码比覆盖类中方法的代码明显更可疑。