代码之家  ›  专栏  ›  技术社区  ›  fuentesjr

为什么python代码使用len()函数而不是length方法?

  •  185
  • fuentesjr  · 技术社区  · 16 年前

    我知道巨蟒有 len() 用于确定字符串大小的函数,但我想知道为什么它不是字符串对象的方法。

    更新

    好吧,我意识到我错了。 __len__() 实际上是一个字符串对象的方法。在Python中看到面向对象的代码在字符串对象上使用len函数似乎很奇怪。而且,看到它也很奇怪 __len__ 而不仅仅是Len。

    8 回复  |  直到 6 年前
        1
  •  167
  •   Jonny Buchanan    13 年前

    字符串确实具有长度方法: __len__()

    python中的协议是在具有长度的对象上实现此方法,并使用内置的 len() 函数,它为您调用它,类似于您将实现的方式 __iter__() 使用内置的 iter() 函数(或让方法在后台为您调用)对不可迭代的对象。

    Emulating container types 更多信息。

    下面是关于python协议主题的一篇好文章: Python and the Principle of Least Astonishment

        2
  •  84
  •   Community clintgh    7 年前

    吉姆的回答 this question 可以帮忙,我把它抄在这里。引用guido van rossum:

    首先,我选择len(x)而不是x.len(),原因是hci(def_uuLen_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu实际上有两个相互交织的原因,两个是HCI:

    (a)对于某些操作,前缀表示法的读取效果比后缀前缀(和infix!)运算在数学中有着悠久的传统,它喜欢用符号来表示视觉帮助数学家思考问题。比较我们把x*这样的公式(a+b)改写为x的容易程度。 A+X 用一个原始的OO符号做同样的事情是笨拙的。

    (b)当我读到表示len(x)的代码时,我知道它要求的是某物的长度。这告诉我两件事:结果是一个整数,参数是某种容器。相反,当我读取x.len()时,我必须知道x是一种实现接口或从具有标准len()的类继承的容器。当一个没有实现映射的类有一个get()或keys()方法,或者某个文件没有一个write()方法时,我们偶尔会遇到这样的困惑。

    用另一种方式说同样的话,我认为__len__是一种内置操作。我不想失去它。········

        3
  •  37
  •   unmounted    16 年前

    有一个 len 方法:

    >>> a = 'a string of some length'
    >>> a.__len__()
    23
    >>> a.__len__
    <method-wrapper '__len__' of str object at 0x02005650>
    
        4
  •  29
  •   Luciano Ramalho    10 年前

    python是一种实用的编程语言,其原因是 len() 是函数而不是方法 str , list , dict 等等是务实的。

    这个 Le() 内置函数直接处理内置类型:cpython实现 Le() 实际返回 ob_size 中的字段 PyVarObject C struct 它表示内存中任何可变大小的内置对象。这是 许多的 比调用方法更快——不需要进行属性查找。获取集合中的项数是一种常见的操作,必须对以下基本和不同类型有效工作: STR , 列表 , array.array 等。

    但是,为了提高一致性,在应用时 len(o) 对于用户定义的类型,python调用 o.__len__() 作为后退。 __len__ , __abs__ 以及 Python Data Model 使创建行为类似于内置组件的对象变得容易,从而使我们称之为“pythonic”的表达性和高度一致的API成为可能。

    通过实现特殊的方法,您的对象可以支持迭代、重载中缀运算符、管理上下文 with 块等。您可以将数据模型视为使用Python语言本身作为框架的一种方式,在该框架中,您创建的对象可以无缝集成。

    第二个原因,由guido van rossum的引用支持 this one ,是否更容易读写? len(s) s.len() .

    记号法 莱恩(S) 与带有前缀符号的一元运算符一致,例如 abs(n) . Le() 使用的频率比 abs() 而且它应该很容易写。

    可能还有一个历史原因:在python之前的abc语言中(在它的设计中非常有影响),有一个一元运算符编写为 #s 这意味着 莱恩(S) .

        5
  •  12
  •   Alex Coventry    16 年前
    met% python -c 'import this' | grep 'only one'
    There should be one-- and preferably only one --obvious way to do it.
    
        6
  •  3
  •   jpp    6 年前

    这里有一些很好的答案,所以在我给出自己的答案之前,我想突出一些我在这里读过的宝石(没有Ruby双关语)。

    • Python不是一种纯粹的OOP语言——它是一种通用的多范式语言,允许程序员使用他们最熟悉的范式和/或最适合他们解决方案的范式。
    • python有一流的函数,所以 len 实际上是一个物体。另一方面,Ruby没有一流的功能。所以 伦恩 函数对象有自己的方法,可以通过运行 dir(len) .

    如果您不喜欢这种在您自己的代码中工作的方式,那么使用您首选的方法(参见下面的示例)重新实现容器是很简单的。

    >>> class List(list):
    ...     def len(self):
    ...         return len(self)
    ...
    >>> class Dict(dict):
    ...     def len(self):
    ...         return len(self)
    ...
    >>> class Tuple(tuple):
    ...     def len(self):
    ...         return len(self)
    ...
    >>> class Set(set):
    ...     def len(self):
    ...         return len(self)
    ...
    >>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
    >>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
    >>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
    >>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
    >>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
    >>>
    >>> for container in my_containers:
    ...     print container.len()
    ...
    15
    2
    15
    15
    
        7
  •  1
  •   Wouter J schlicki    12 年前

    你也可以说

    >> x = 'test'
    >> len(x)
    4
    

    使用python 2.7.3。

        8
  •  -1
  •   Nick Stinemates    16 年前

    不是吗?

    >>> "abc".__len__()
    3