我認爲原因是這樣的基本操作可以在與容器相同的接口的迭代器上完成。但是,它實際上不適用於len:
def foo():
for i in range(10):
yield i
print len(foo())
...因TypeError失敗。 len()不會消耗和計算迭代器;它只適用於調用__len__
的對象。
所以,就我而言,len()不應該存在。說obj.len比len(obj)更自然,並且與其他語言和標準庫更加一致。我們不會說append(lst,1);我們說lst.append(1)。有一個單獨的全局長度方法是一個奇怪的,不一致的特例,並且在全局命名空間中吃了一個非常明顯的名字,這是Python的一個非常不好的習慣。
這與鴨打字無關;你可以說getattr(obj, "len")
決定你是否可以像使用getattr(obj, "__len__")
一樣容易 - 更加一致 - 地使用len。
所有這些,像語言疣一樣 - 對於那些認爲這是一個疣的人 - 這是一個容易與之共處的人。
另一方面,最小和最大做工作迭代器,除了任何特定的對象,它們的使用。這是簡單的,所以我就舉一個例子:
import random
def foo():
for i in range(10):
yield random.randint(0, 100)
print max(foo())
然而,沒有__min__
或__max__
方法來覆蓋這些行爲,因此沒有爲有序容器提供高效的檢索中沒有一致的方法。如果一個容器按照您要搜索的同一個鍵進行排序,則最小/最大值是O(1)操作而不是O(n),並且唯一的方法是通過不同的不一致的方法公開該操作。 (當然,這可以用相對簡單的語言修正)。
爲了跟進另一個問題:它阻止使用Python的方法綁定。舉一個簡單的,人爲的例子,你可以這樣做是爲了提供一個功能值添加到列表:
def add(f):
f(1)
f(2)
f(3)
lst = []
add(lst.append)
print lst
,這適用於所有的成員函數。儘管如此,你不能用min,max或len來實現,因爲它們不是它們操作對象的方法。相反,你必須求助於functools.partial,這是一種在其他語言中很常見的笨拙的第二類解決方法。
當然,這是一個不常見的情況;但是不常見的情況告訴我們一種語言的一致性。
我個人發現'min(1,2)'和'min([1,2])'是非常一致的。不是所有的東西都應該是Java,像 – 2009-10-27 01:06:16
@TomLeys:'len(x)'如何與像'x.foo()'這樣的方法調用保持一致?他們都是對象x的操作,不是嗎?這不是關於像Java一樣。這符合[最低驚奇原則](http://en.wikipedia.org/wiki/Principle_of_least_surprise)。 Ruby遵循這個原則。 – 2011-10-19 23:18:08