"{1} {0} {1!r}".format(obj0, obj1) # reorders, repeats, and and calls repr on obj1
"{0.value:.{0.precision}f}".format(obj) # uses attrs of obj for value and format spec
"{obj[name]}".format(obj=my_dict) # takes argument by keyword, and does an item lookup
First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:
(a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.
(b) When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.
Saying the same thing in another way, I see ‘len‘ as a built-in operation. I’d hate to lose that. /…/
There's additional reasoning about len in the Design and History FAQ. Although it's not as complete or as good of an answer, it is indisputably official. – abarnert
Also, as far as the namespace-pollution issue with Ruby and JS, it's worth pointing out that this is an inherent problem with dynamically-typed languages. In statically-typed languages as diverse as Haskell and C++, type-specific free functions are not only possible, but idiomatic. (See The Interface Principle.) But in dynamically-typed languages like Ruby, JS, and Python, free functions must be universal. A big part of language/library design for dynamic languages is picking the right set of such functions.
我认为
format
和str.format
做不同的事情。即使您可以对两者都使用str.format
,但是有单独的版本是有意义的。顶层
format
函数是所有对象都支持的新“格式化协议”的一部分。它只调用所传递对象的__format__
方法,并返回一个字符串。这是一个低级任务,Python的风格通常是为这些任务提供内置函数。Paulo Scardine的回答解释了其中的一些基本原理,但我不认为它真正解决了format
和str.format
之间的区别。str.format
方法更高级,也更复杂。它不仅可以将多个对象格式化为一个结果,还可以对这些对象进行重新排序、重复、索引和其他各种转换。不要只想着"{}".format(obj)
。str.format
实际上是为更复杂的任务而设计的,比如:对于每个项的低级格式化,
str.format
依赖于格式协议的相同机制,因此它可以将自己的工作集中在更高级的内容上。我怀疑它实际上调用了内置的format
,而不是它的参数__format__
方法,但这是一个实现细节。虽然
("{:"+format_spec+"}").format(obj)
可以保证给出与format(obj, format_spec)
相同的结果,但我怀疑后者会更快一些,因为它不需要解析格式字符串来检查任何复杂的内容。然而,在实际程序中,开销可能会在噪声中丢失。当谈到使用(包括堆栈溢出的例子)时,您可能会看到更多的
str.format
使用,这仅仅是因为一些程序员不知道format
,这是新的,而且相当模糊。相反,很难避免str.format
(除非您决定对所有格式使用%
运算符)。因此,理解一个str.format
调用的容易程度(对您和您的程序员同事来说)可能超过任何性能考虑。tldr;
format
只需调用obj.__format__
,并由str.format
方法使用,该方法可以执行更高级别的操作。对于较低的层次来说,教一个对象如何格式化它自己是有意义的。只是句法语
此函数与
str.format
共享名称和格式规范这一事实可能会产生误导。str.format
的存在很容易解释:它执行复杂的字符串插值(替换旧的%
运算符);format
可以将单个对象格式化为字符串,这是str.format
规范的最小子集。那么,为什么我们需要format
?format
函数是在某些OO语言中找到的obj.format('fmt')
构造的替代方法。这个决定与len
(关于Python为什么使用函数len(x)
,而不是像Javascript或Ruby这样的属性x.length
)的基本原理是一致的。当一种语言采用
obj.format('fmt')
构造(或者obj.length
,obj.toString
等等)时,类就不能有一个名为format
(或者length
,toString
的属性,这是你的主意)否则它会使标准方法与该语言相形见绌。在这种情况下,语言设计者将防止名称冲突的责任推给程序员。Python非常喜欢PoLA,并对内置项采用了
__dunder__
(双下划线)约定,以尽量减少用户定义的属性与语言内置项之间发生冲突的可能性。所以obj.format('fmt')
变成obj.__format__('fmt')
,当然你可以调用obj.__format__('fmt')
,而不是format(obj, 'fmt')
(就像你可以调用obj.__len__()
,而不是len(obj)
)。用你的例子:
哪一个更干净更容易打字?Python设计非常实用,它不仅更简洁,而且与Python的duck-typed方法很好地结合在一起,使语言设计者可以自由地更改/扩展底层实现,而不破坏遗留代码。
PEP 3101引入了新的
str.format
方法和format
内置,没有对format
函数的基本原理做任何评论,但是实现显然只是syntactic sugar:我把箱子放在这里。
圭多怎么说的(还是官方的?)
引用关于
len
的BDFL:来源:pyfaq@effbot.org(原始帖子here也有Guido正在回答的原始问题)。Abarnert还建议:
这是一个实际问题还是只是语法上的挑剔?
在Python、Ruby或Javascript等语言中,这是一个非常实际和现实的问题,因为在动态类型语言中,任何可变对象实际上都是一个名称空间,私有方法或属性的概念是一个约定问题。可能我在他的评论中说得比abarnert更好:
例如,我只留下Ember.js来支持Angular.js,因为I was tired of namespace conflicts in Ember;Angular使用一种优雅的类似Python的策略来处理这个问题,该策略是在内置方法前面加上前缀(在Angular中加上
$thing
,而不是在Python中加下划线),因此它们不会与用户定义的方法和属性冲突。是的,整个__thing__
并不是特别漂亮,但我很高兴Python采用了这种方法,因为它非常明确,并且避免了PoLA类关于对象名称空间冲突的错误。相关问题 更多 >
编程相关推荐