tldr; format
只是打电话obj.__format__
并被使用str.format
方法可以做更高层次的事情。对于较低级别来说,教导对象如何格式化自身是有意义的。
它只是语法糖
事实上,该函数与以下函数共享名称和格式规范:str.format
可能会产生误导。的存在str.format
很容易解释:它进行复杂的字符串插值(替换旧的%
操作员);format
可以将单个对象格式化为字符串,即最小的子集str.format
规格。那么,为什么我们需要format
?
The format
函数是一个替代obj.format('fmt')
在一些结构中发现OO https://en.wikipedia.org/wiki/Object-oriented_programming语言。这一决定与该决定的理由是一致的len
(关于为什么Python使用函数len(x)
而不是财产x.length
like JavaScript https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/length或红宝石)。
当一种语言采用obj.format('fmt')
构造(或obj.length
, obj.toString
等等),类被阻止拥有名为format
(or length
, toString
,你明白了) - 否则它会影响语言的标准方法。在这种情况下,语言设计者将防止名称冲突的负担交给了程序员。
Python非常喜欢PoLA http://en.wikipedia.org/wiki/Principle_of_least_astonishment并通过了__dunder__
(双下划线)内置函数约定,以尽量减少用户定义的属性和语言内置函数之间发生冲突的可能性。所以obj.format('fmt')
变成obj.__format__('fmt')
,当然你可以打电话obj.__format__('fmt')
代替format(obj, 'fmt')
(同样的方式你可以打电话obj.__len__()
代替len(obj)
).
使用你的例子:
>>> '{0:x}'.format(13)
'd'
>>> (13).__format__('x')
'd'
>>> format(13, 'x')
'd'
哪一个更干净、更容易打字? Python的设计非常务实,不仅干净而且与Python的风格非常契合鸭型 http://en.wikipedia.org/wiki/Duck_typing接近OO https://en.wikipedia.org/wiki/Object-oriented_programming并让语言设计者可以自由地更改/扩展底层实现,而不会破坏遗留代码。
The PEP 3101 http://www.python.org/dev/peps/pep-3101/推出了新的str.format
方法和format
内置,没有任何理由的评论format
函数,但实现显然只是句法糖 http://en.wikipedia.org/wiki/Syntactic_sugar:
def format(value, format_spec):
return value.__format__(format_spec)
我的观点就在这里。
Guido 对此有何评论(或者是官方的?)
引用非常BDFL http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life about len
:
首先我选择的是len(x)
over x.len()
for HCI https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction原因(def __len__()
来得很晚)。实际上有两个相互交织的原因HCI https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction:
(a) 对于某些运算,前缀表示法读起来比后缀更好——前缀(和中缀!)运算在数学中有着悠久的传统,它喜欢视觉帮助数学家思考问题的符号。比较一下我们重写公式的简单性,例如x*(a+b)
into x*a + x*b
使用原始的 OO 表示法做同样的事情是很笨拙的。
(b) 当我读到这样的代码时len(x)
我知道它在询问某物的长度。这告诉我两件事:结果是一个整数,参数是某种容器。相反,当我读到x.len()
,我必须已经知道x
是某种实现接口或继承自具有标准的类的容器len()
。见证一下当一个没有实现映射的类有一个映射时我们偶尔会遇到的混乱get()
or keys()
方法,或者不是文件的东西有write()
method.
用另一种方式说同样的事情,我明白了‘len
' 作为内置操作。我不想失去它。 /…/
source: [电子邮件受保护] http://effbot.org/pyfaq/why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list.htm(原帖here http://mail.python.org/pipermail/python-3000/2006-November/004643.html还有 Guido 正在回答的原始问题)。Abarnert https://stackoverflow.com/users/908494/abarnert还建议:
还有关于 len 的额外推理设计和历史常见问题解答 http://docs.python.org/2/faq/design.html#why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list。尽管它不是那么完整或那么好的答案,但它无疑是官方的。 –abarnert https://stackoverflow.com/users/908494/abarnert
这是一个实际问题还是只是语法挑剔?
对于像 Python 这样的语言来说,这是一个非常实际和现实的问题,Ruby https://groups.google.com/forum/?fromgroups#!topic/rubymotion/kiQTDaMY7As或 Javascript,因为在动态类型语言中,任何可变对象实际上都是命名空间,并且私有方法或属性的概念是约定问题。可能我无法说得比abarnert https://stackoverflow.com/users/908494/abarnert在他的评论中:
另外,就 Ruby 和 JS 的命名空间污染问题而言,值得指出的是,这是动态类型语言的固有问题。在 Haskell 和 C++ 等各种静态类型语言中,特定于类型的自由函数不仅是可能的,而且是惯用的。 (参见接口原理 http://www.gotw.ca/publications/mill02.htm.) 但在 Ruby、JS 和 Python 等动态类型语言中,自由函数必须是通用的。动态语言的语言/库设计的一个重要部分是选择正确的此类函数集。
例如,我刚刚离开Ember.js http://emberjs.com/有利于Angular.js http://angularjs.org/因为我厌倦了 Ember 中的命名空间冲突 https://stackoverflow.com/questions/16515900/reserved-atribute-names-in-ember-js-models; Angular 使用一种优雅的类似 Python 的策略来处理这个问题,即为内置方法添加前缀(使用$thing
在 Angular 中,而不是像 python 那样的下划线),因此它们不会与用户定义的方法和属性冲突。是的,整个__thing__
不是特别漂亮,但我很高兴 Python 采用了这种方法,因为它非常明确并且避免了PoLA http://en.wikipedia.org/wiki/Principle_of_least_astonishment有关对象命名空间冲突的错误类别。