<p><strong>tldr;</strong><code>format</code>只需调用<code>obj.__format__</code>,并由<code>str.format</code>方法使用,该方法可以执行更高级别的操作。对于较低的层次来说,教一个对象如何格式化它自己是有意义的。</p>
<h2>只是句法语</h2>
<p>此函数与<code>str.format</code>共享名称和格式规范这一事实可能会产生误导。<code>str.format</code>的存在很容易解释:它执行复杂的字符串插值(替换旧的<code>%</code>运算符);<code>format</code>可以将单个对象格式化为字符串,这是<code>str.format</code>规范的最小子集。那么,为什么我们需要<code>format</code>?</p>
<p><code>format</code>函数是在某些<a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="nofollow noreferrer">OO</a>语言中找到的<code>obj.format('fmt')</code>构造的替代方法。这个决定与<code>len</code>(关于Python为什么使用函数<code>len(x)</code>,而不是像<a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/length" rel="nofollow noreferrer">Javascript</a>或Ruby这样的属性<code>x.length</code>)的基本原理是一致的。</p>
<p>当一种语言采用<code>obj.format('fmt')</code>构造(或者<code>obj.length</code>,<code>obj.toString</code>等等)时,类就不能有一个名为<code>format</code>(或者<code>length</code>,<code>toString</code>的属性,这是你的主意)否则它会使标准方法与该语言相形见绌。在这种情况下,语言设计者将防止名称冲突的责任推给程序员。</p>
<p>Python非常喜欢<a href="http://en.wikipedia.org/wiki/Principle_of_least_astonishment" rel="nofollow noreferrer">PoLA</a>,并对内置项采用了<code>__dunder__</code>(双下划线)约定,以尽量减少用户定义的属性与语言内置项之间发生冲突的可能性。所以<code>obj.format('fmt')</code>变成<code>obj.__format__('fmt')</code>,当然你可以调用<code>obj.__format__('fmt')</code>,而不是<code>format(obj, 'fmt')</code>(就像你可以调用<code>obj.__len__()</code>,而不是<code>len(obj)</code>)。</p>
<p>用你的例子:</p>
<pre><code>>>> '{0:x}'.format(13)
'd'
>>> (13).__format__('x')
'd'
>>> format(13, 'x')
'd'
</code></pre>
<p>哪一个更干净更容易打字?Python设计非常实用,它不仅更简洁,而且与Python的<a href="http://en.wikipedia.org/wiki/Duck_typing" rel="nofollow noreferrer">duck-typed</a>方法很好地结合在一起,使语言设计者可以自由地更改/扩展底层实现,而不破坏遗留代码。</p>
<p><a href="http://www.python.org/dev/peps/pep-3101/" rel="nofollow noreferrer">PEP 3101</a>引入了新的<code>str.format</code>方法和<code>format</code>内置,没有对<code>format</code>函数的基本原理做任何评论,但是实现显然只是<a href="http://en.wikipedia.org/wiki/Syntactic_sugar" rel="nofollow noreferrer">syntactic sugar</a>:</p>
<pre><code>def format(value, format_spec):
return value.__format__(format_spec)
</code></pre>
<p>我把箱子放在这里。</p>
<h2>圭多怎么说的(还是官方的?)</h2>
<p>引用关于<code>len</code>的<a href="http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life" rel="nofollow noreferrer">BDFL</a>:</p>
<blockquote>
<p>First of all, I chose <code>len(x)</code> over <code>x.len()</code> for <a href="https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction" rel="nofollow noreferrer">HCI</a> reasons (<code>def __len__()</code> came much later). There are two intertwined reasons actually, both <a href="https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction" rel="nofollow noreferrer">HCI</a>:</p>
<p>(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 <code>x*(a+b)</code> into <code>x*a + x*b</code> to the clumsiness of doing the same thing using a raw OO notation.</p>
<p>(b) When I read code that says <code>len(x)</code> 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 <code>x.len()</code>, I have to already know that <code>x</code> is some kind of container implementing an interface or inheriting from a class that has a standard <code>len()</code>. Witness the confusion we occasionally have when a class that is not implementing a mapping has a <code>get()</code> or <code>keys()</code> method, or something that isn’t a file has a <code>write()</code> method.</p>
<p>Saying the same thing in another way, I see ‘<code>len</code>‘ as a built-in operation. I’d hate to lose that. /…/</p>
</blockquote>
<p>来源:<a href="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" rel="nofollow noreferrer">pyfaq@effbot.org</a>(原始帖子<a href="http://mail.python.org/pipermail/python-3000/2006-November/004643.html" rel="nofollow noreferrer">here</a>也有Guido正在回答的原始问题)。<a href="https://stackoverflow.com/users/908494/abarnert">Abarnert</a>还建议:</p>
<blockquote>
<p>There's additional reasoning about len in the <a href="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" rel="nofollow noreferrer">Design and History FAQ</a>. Although it's not as complete or as good of an answer, it is indisputably official. – <a href="https://stackoverflow.com/users/908494/abarnert">abarnert</a></p>
</blockquote>
<h2>这是一个实际问题还是只是语法上的挑剔?</h2>
<p>在Python、<a href="https://groups.google.com/forum/?fromgroups#!topic/rubymotion/kiQTDaMY7As" rel="nofollow noreferrer">Ruby</a>或Javascript等语言中,这是一个非常实际和现实的问题,因为在动态类型语言中,任何可变对象实际上都是一个名称空间,私有方法或属性的概念是一个约定问题。可能我在他的评论中说得比<a href="https://stackoverflow.com/users/908494/abarnert">abarnert</a>更好:</p>
<blockquote>
<p>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 <a href="http://www.gotw.ca/publications/mill02.htm" rel="nofollow noreferrer">Interface Principle</a>.) 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.</p>
</blockquote>
<p>例如,我只留下<a href="http://emberjs.com/" rel="nofollow noreferrer">Ember.js</a>来支持<a href="http://angularjs.org/" rel="nofollow noreferrer">Angular.js</a>,因为<a href="https://stackoverflow.com/questions/16515900/reserved-atribute-names-in-ember-js-models">I was tired of namespace conflicts in Ember</a>;Angular使用一种优雅的类似Python的策略来处理这个问题,该策略是在内置方法前面加上前缀(在Angular中加上<code>$thing</code>,而不是在Python中加下划线),因此它们不会与用户定义的方法和属性冲突。是的,整个<code>__thing__</code>并不是特别漂亮,但我很高兴Python采用了这种方法,因为它非常明确,并且避免了<a href="http://en.wikipedia.org/wiki/Principle_of_least_astonishment" rel="nofollow noreferrer">PoLA</a>类关于对象名称空间冲突的错误。</p>