組み込みの format
関数は、単一のオブジェクトをフォーマットする場合に特に使用される str.format
メソッドのサブセットのようです。
例えば。
>>> format(13, 'x')
'd'
明らかに好ましい
>>> '{0:x}'.format(13)
'd'
iMOの方が見栄えがよくなりますが、すべてのケースでstr.format
を使用して、物事を簡単にするのはなぜですか?これらは両方とも2.6
で導入されたので、両方を同時に使用することには十分な理由があるはずです。それは何ですか?
編集:str.format
とformat
について尋ねていましたが、(13).format
がない理由ではありませんでした
format
と_str.format
_は異なることをしていると思います。両方に_str.format
_を使用することもできますが、バージョンを分けることは理にかなっています。
トップレベルのformat
関数は、すべてのオブジェクトがサポートする新しい「フォーマットプロトコル」の一部です。渡されたオブジェクトの___format__
_メソッドを呼び出すだけで、文字列が返されます。これは低レベルのタスクであり、Pythonのスタイルは通常それらのための組み込み関数を持つことです。 Paulo Scardineの回答はこれの理論的根拠のいくつかを説明していますが、format
と_str.format
_の動作の違いに実際に対処しているとは思いません。
_str.format
_メソッドはもう少し高レベルで、もう少し複雑です。複数のオブジェクトを1つの結果にフォーマットするだけでなく、オブジェクトの並べ替え、繰り返し、インデックス付け、その他のさまざまな変換を行うこともできます。 "{}".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
_
各項目の低レベルのフォーマットについては、_str.format
_はフォーマットプロトコルの同じメカニズムに依存しているため、より高レベルの要素に独自の努力を集中できます。引数の___format__
_メソッドではなく、組み込みのformat
を実際に呼び出すのではないかと思いますが、これは実装の詳細です。
_("{:"+format_spec+"}").format(obj)
_はformat(obj, format_spec)
と同じ結果を提供することが保証されていますが、複雑なものをチェックするためにフォーマット文字列を解析する必要がないため、後者は少し高速になると思いますもの。ただし、実際のプログラムでは、ノイズによってオーバーヘッドが失われる可能性があります。
使用法(スタックオーバーフローの例を含む)になると、一部のプログラマーがformat
を知らないため、より多くの_str.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)
を使用する理由x.length
like JavaScript または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'
どちらがすっきりしていて入力が簡単ですか? Pythonデザインは非常に実用的です。デザインがすっきりしているだけでなく、Pythonの duck-typed アプローチ [〜#〜] oo [ 〜#〜] そして、言語設計者に、レガシーコードを壊すことなく、基礎となる実装を変更/拡張する自由を与えます。
PEP 3101 は、新しいstr.format
メソッドとformat
ビルトインを導入しましたが、format
関数の根拠に関するコメントはありませんが、実装は明らかにただ 構文糖 :
def format(value, format_spec):
return value.__format__(format_spec)
そしてここで私は私のケースを休ませる。
非常に引用 [〜#〜] bdfl [〜#〜] についてlen
:
まず第一に、私は [〜#〜] hci [〜#〜] 理由のために
len(x)
ではなくx.len()
を選択しました(def __len__()
はずっと後で来ました) 。実際には2つの理由が絡み合っています [〜#〜] hci [〜#〜] :(a)一部の演算では、接頭表記は単にpostfixよりも読みやすくなります。接頭辞(および下接!)演算は、数学において長い間、伝統があり、ビジュアルが問題について数学者が考える助けとなる表記法を好みます。
x*(a+b)
のような数式をx*a + x*b
に書き換える簡単な方法と、生のOO表記法を使用して同じことを行うことの不手際を比較してください。(b)
len(x)
と書かれたコードを読んだとき、何かの長さを要求していることを知っています。これは2つのことを教えてくれます。結果は整数であり、引数はなんらかのコンテナです。逆に、x.len()
を読んだとき、x
は、インターフェイスを実装するか、標準のlen()
を持つクラスから継承するコンテナの一種であることをすでに知っている必要があります。マッピングを実装していないクラスにget()
またはkeys()
メソッドが含まれている場合や、ファイルではないクラスにwrite()
メソッドが含まれている場合に発生する混乱を確認してください。同じことを別の言い方で言うと、「
len
」は組み込みの操作と見なされます。それを失うのは嫌だ。 /…/
出典: [email protected] (元の投稿 ここ には、Guidoが回答した元の質問もあります)。 Abarnert は以下も提案します:
デザインと履歴に関するFAQ には、lenに関する追加の推論があります。それは完全ではありませんし、答えの良いものでもありませんが、疑いもなく公式です。 – abarnert
これは、Python、 Ruby 、Javascriptなどの言語では非常に実用的で現実的な問題です。動的に型付けされた言語では、変更可能なオブジェクトは事実上名前空間であり、プライベートメソッドまたは属性の概念は重要です。コンベンション。多分私はそれを彼のコメントで abarnert よりも上に置くことができませんでした:
また、RubyおよびJSに関する名前空間汚染の問題に関する限り、これは動的に型付けされた言語に固有の問題であることを指摘する価値があります。HaskellおよびC++では、型固有のフリー関数が可能であるだけでなく、慣用的です( インターフェース原理 を参照してください)。ただし、Ruby、JS、Pythonなどの動的に型付けされた言語では、フリー関数はユニバーサルでなければなりません。A動的言語の言語/ライブラリ設計の大部分は、そのような関数の適切なセットを選択することです。
たとえば、 Ember.js を残して Angular.js を支持しました Emberでの名前空間の競合にうんざりしていたため ; Angularは、組み込みメソッドに接頭辞を付けるというPythonのようなエレガントな戦略を使用してこれを処理します(Pythonのようなアンダースコアの代わりに、Angularでは$thing
を使用します)。定義されたメソッドとプロパティです。はい、__thing__
全体は特にきれいではありませんが、Pythonは非常に明示的で PoLA オブジェクト名前空間の衝突に関するバグのクラス。