为什么Python有格式函数和格式方法

jam*_*lak 35 python string format python-2.6 built-in

formatbuiltins中的函数似乎是str.format专门用于格式化单个对象的方法的子集.

例如.

>>> format(13, 'x')
'd'
Run Code Online (Sandbox Code Playgroud)

显然更喜欢

>>> '{0:x}'.format(13)
'd'
Run Code Online (Sandbox Code Playgroud)

和IMO它确实看起来更好,但为什么不只是str.format在每种情况下使用,以使事情更简单?这两个都是介绍的,2.6所以必须有一个很好的理由同时拥有它们,它是什么?

编辑:我是问str.formatformat,不是我们没有(13).format

Pau*_*ine 39

tldr; format只是调用obj.__format__并且被str.format更高级别的东西使用的方法使用.对于较低级别,教会对象如何格式化自己是有意义的.

这只是语法糖

此函数共享名称和格式规范的事实str.format可能会产生误导.存在str.format很容易解释:它做复杂的字符串插值(替换旧的%运算符); format可以将单个对象格式化为字符串,即str.format规范的最小子集.那么,我们为什么需要format呢?

format函数是obj.format('fmt')某些OO语言中的构造的替代.这个决定与len(为什么Python使用函数len(x)而不是x.lengthJavascript或Ruby 这样的属性)的基本原理一致.

当一种语言采用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)).

使用你的例子:

>>> '{0:x}'.format(13)
'd'
>>> (13).__format__('x')
'd'
>>> format(13, 'x')
'd'
Run Code Online (Sandbox Code Playgroud)

哪一个更干净,更容易打字?Python设计非常实用,它不仅更干净,而且与Python的鸭式OO方法完全一致,并使语言设计人员可以自由地更改/扩展底层实现,而不会破坏遗留代码.

PEP 3101推出了新的str.format方法,并format没有对在理任何评论内置format功能,但实现显然只是语法糖:

def format(value, format_spec):
    return value.__format__(format_spec)
Run Code Online (Sandbox Code Playgroud)

在这里,我休息一下.

Guido说的是什么(或者是官方的吗?)

报价非常BDFL有关len:

首先,我选择len(x)x.len()HCI的原因(def __len__()来得更高版本).实际上有两个相互交织的原因,都是人机交互:

(a)对于某些操作,前缀表示法只比读后缀更好 - 前缀(和中缀!)操作在数学中有悠久的传统,它喜欢视觉效果帮助数学家思考问题的符号.比较与我们改写像公式简单x*(a+b)x*a + x*b使用原始OO符号做同样的事情的笨拙.

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

用另一种方式说同样的事情,我认为' len'是一种内置操作.我不想失去那个./ ...... /

来源:pyfaq@effbot.org(原帖这里也有Guido回答的原始问题).Abarnert还建议:

设计和历史常见问题解答中还有关于len的其他推理.虽然它不是一个完整或好的答案,但它无疑是官方的.- abarnert

这是一个实际问题还是只是语法挑剔?

在Python,Ruby或Javascript 等语言中,这是一个非常实际和现实世界的关注点,因为在动态类型语言中,任何可变对象实际上都是命名空间,私有方法或属性的概念是常规问题.在他的评论中,我可能不会比abarnert更好:

此外,就Ruby和JS的名称空间污染问题而言,值得指出的是,这是动态类型语言的固有问题.在像Haskell和C++这样多种类型的静态类型语言中,特定于类型的自由函数不仅是可行的,而且是惯用的.(请参阅接口原理.)但是在Ruby,JS和Python等动态类型语言中,自由函数必须是通用的.动态语言的语言/库设计的很大一部分是选择正确的这类函数.

例如,我刚刚离开Ember.js而支持Angular.js,因为我厌倦了Ember中的命名空间冲突 ; Angular使用优雅的类似于Python的策略来处理这个问题,该策略为内置方法添加前缀(使用$thingAngular,而不是像python那样使用下划线),因此它们不会与用户定义的方法和属性冲突.是的,整体__thing__并不是特别漂亮,但我很高兴Python采用这种方法,因为它非常明确,并且避免了PoLA类关于对象命名空间冲突的错误.

  • 此外,就Ruby和JS的名称空间污染问题而言,值得指出的是,这是动态类型语言的固有问题.在像Haskell和C++这样多种类型的静态类型语言中,特定于类型的自由函数不仅是可行的,而且是惯用的.(参见[The Interace Principle](http://www.gotw.ca/publications/mill02.htm).)但是在Ruby,JS和Python等动态类型语言中,自由函数必须是通用的.动态语言的语言/库设计的很大一部分是选择正确的这类功能. (5认同)
  • 我不会说这两种情况完全相同(`'{0}'.format` 与 `x.len` 不一样,它在某种程度上类似于 `''.join`)但我知道在哪里你来自哪里,这是有道理的。 (2认同)
  • @poorsod:[pyfaq -(半官方)Python 常见问题区](http://effbot.org/pyfaq/why-does-python-use-methods-for-some-functionality-eg-list-index-but -functions-for-other-eg-len-list.htm) (2认同)
  • [设计和历史常见问题解答](http://docs.python.org/2/faq/design.html#why-does-python-use-methods-for-some-functionality- eg-list-index-but-functions-for-other-eg-len-list)。虽然它没有那么完整或那么好,但它无疑是官方的。 (2认同)

Blc*_*ght 6

我认为formatstr.format做不同的事情.即使您可以同时使用str.format这两个版本,也可以使用单独的版本.

顶级format功能是所有对象支持的新"格式化协议"的一部分.它只是调用__format__传递的对象的方法,并返回一个字符串.这是一个低级别的任务,Python的风格通常是为那些内置函数.Paulo Scardine的回答解释了一些基本原理,但我认为它并没有真正解决了什么formatstr.format做什么之间的差异.

str.format方法有点高级,也有点复杂.它不仅可以将多个对象格式化为单个结果,还可以对对象进行重新排序,重复,索引和执行各种其他转换.不要只想到"{}".format(obj).str.format实际上是为了更复杂的任务而设计的,例如:

"{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
Run Code Online (Sandbox Code Playgroud)

对于每个项目的低级格式化,str.format依赖于格式协议的相同机制,因此它可以将自己的努力集中在更高级别的东西上.我怀疑它实际上是调用内置format函数,而不是它的参数__format__方法,但这是一个实现细节.

虽然("{"+format_code+"}").format(obj)保证给出相同的结果format(obj, format_code),但我怀疑后者会更快一些,因为它不需要解析格式字符串来检查任何复杂的东西.然而,实际程序中的噪声可能会丢失开销.

当涉及到使用时(包括Stack Overflow上的示例),您可能会看到更多的str.format使用,因为一些程序员不知道format,这既新又相当模糊.相比之下,很难避免str.format(除非您决定坚持使用%运算符进行所有格式化).因此,理解str.format呼叫的容易程度(对于您和您的同事程序员而言)可能超过任何性能考虑因素.

  • 保罗在他的回答中付出了很多努力,它看起来像是那些包罗万象的指南之一。然而他正在回答一个不存在的问题。我想知道为什么我们不总是使用“{0}”.format。是的,我理解“format()”是“__format__”的语法糖,Paulo 深入探讨了为什么这对 Python 有好处。但这不是我的问题。你的回答解释了原因并且符合逻辑。我不同意 Python 有两个版本,因为它违背了“一种方法”的口头禅,但是哦,好吧。为了简单起见,我只使用“{0}”格式。 (2认同)