回答:
文字列にはlengthメソッドがあります。 __len__()
Pythonのプロトコルは、長さを持ち、組み込みlen()
関数を使用するオブジェクトにこのメソッドを実装することです。組み込み関数は、組み込み関数を実装__iter__()
して使用iter()
する方法(またはメソッドを背後で呼び出す方法)に似ています。反復可能なオブジェクトでのシーン)。
詳細については、コンテナタイプのエミュレートを参照してください。
Pythonのプロトコルについての良い読み物は次のとおりです。Pythonと最小驚きの原則
__iter__
、またはのみ__getitem__
でイテラブルを作成でき、iter(x)
どちらの方法でも機能します。__bool__
または__len__
でブールコンテキストで使用可能なオブジェクトを作成でき、bool(x)
どちらの方法でも機能します。等々。Arminはリンクされた投稿でこれについてかなりうまく説明していると思いますが、たとえ彼が説明しなかったとしても、コア
zip
ではなく、トップレベルの関数zip_with
です。等々。すべてがオブジェクトであるからといって、オブジェクトであることはそれぞれについて最も重要なことではありません。
この質問に対するジムの回答が役立つかもしれません。ここにコピーします。グイドファンロッサムの引用:
まず、HCIの理由から、私はx.len()ではなくlen(x)を選択しました(def __len __()はかなり後に登場しました)。実際には2つの理由があり、どちらもHCIです。
(a)一部の操作では、前置記法は単にpostfixよりも読みやすくなります。前置(およびinfix!)操作は数学において長い伝統を有しており、ビジュアルが問題について数学者が考える助けとなる記法を好みます。x *(a + b)のような式をx a + x bに書き換える簡単な方法と、生のOO表記を使用して同じことを行う煩雑さを比較してください。
(b)len(x)と書かれたコードを読んだとき、何かの長さを要求していることがわかります。これは2つのことを教えてくれます。結果は整数であり、引数はなんらかのコンテナです。逆に、x.len()を読んだとき、xはインターフェイスを実装したり、標準のlen()を持つクラスから継承したりするコンテナの一種であることをすでに知っている必要があります。マッピングを実装していないクラスにget()またはkeys()メソッドがある場合、またはファイルではないクラスにwrite()メソッドがある場合にときどき発生する混乱を見てください。
同じことを別の言い方をすると、「len」は組み込みの操作と見なされます。それを失うのは嫌だ。/…/
Pythonは実用的なプログラミング言語であり、len()
関数str
であってlist
、dict
などのメソッドではない理由は実用的です。
len()
組み込み関数ディール直接とビルトインタイプ:のCPythonの実装len()
実際には、の値を返しob_size
、フィールドPyVarObject
Cの構造体を表し、任意の可変サイズ内蔵メモリ内のオブジェクト。これは、メソッドを呼び出すよりもはるかに高速です。属性の検索を行う必要はありません。コレクション内の項目数を取得する一般的な操作であり、このような基本的かつ多様なタイプのために効率的に機能しなければならないstr
、list
、array.array
など
ただし、一貫性を高めるためlen(o)
に、ユーザー定義型に適用する場合、Pythonはo.__len__()
フォールバックとして呼び出します。 __len__
、__abs__
およびPythonデータモデルに記載されているその他すべての特別なメソッドにより、組み込みのように動作するオブジェクトを簡単に作成でき、「Pythonic」と呼ばれる表現力豊かで一貫性の高いAPIが可能になります。
特別なメソッドを実装することにより、オブジェクトは反復をサポートし、インフィックス演算子をオーバーロードし、with
ブロック内のコンテキストを管理できます。データモデルは、Python言語自体を、作成したオブジェクトをシームレスに統合できるフレームワークとして使用する方法と考えることができます。
このようなGuido van Rossumからの引用に裏付けられた2番目の理由は、にlen(s)
比べて読み書きが簡単であることですs.len()
。
表記len(s)
は、のような接頭表記の単項演算子と一致していますabs(n)
。はよりlen()
も頻繁に使用されておりabs()
、書くのと同じくらい簡単であるに値します。
歴史的な理由もあるかもしれません:Pythonに先行する(そしてその設計に非常に影響力があった)ABC言語では、#s
を意味するように書かれた単項演算子がありましたlen(s)
。
met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.
ここにはいくつかの素晴らしい答えがあります。そのため、自分で説明する前に、ここで読んだいくつかの宝石(ルビーのしゃれは意図されていません)を強調したいと思います。
len
、実際にはオブジェクトです。一方、Rubyにはファーストクラスの関数がありません。したがって、len
関数オブジェクトには、を実行して検査できる独自のメソッドがありますdir(len)
。独自のコードでこれが機能する方法が気に入らない場合は、好みの方法を使用してコンテナーを再実装するのは簡単です(以下の例を参照)。
>>> class List(list):
... def len(self):
... return len(self)
...
>>> class Dict(dict):
... def len(self):
... return len(self)
...
>>> class Tuple(tuple):
... def len(self):
... return len(self)
...
>>> class Set(set):
... def len(self):
... return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
... print container.len()
...
15
2
15
15
あなたも言うことができます
>> x = 'test'
>> len(x)
4
Python 2.7.3を使用します。
len
関数はすでに以前の回答で言及されていました。では、この「答え」の意味は何でしょうか。
ここでの残りの回答から欠落しているもの:len
関数は、__len__
メソッドが負でないを返すことを確認しますint
。実際len
のクラスがチェックを回避するために、この動作をオーバーライドすることはできません機能手段です。このように、len(obj)
安全性のレベルを提供しますobj.len()
できない。
例:
>>> class A:
... def __len__(self):
... return 'foo'
...
>>> len(A())
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
len(A())
TypeError: 'str' object cannot be interpreted as an integer
>>> class B:
... def __len__(self):
... return -1
...
>>> len(B())
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
len(B())
ValueError: __len__() should return >= 0
もちろん、len
グローバル変数として再割り当てすることで関数を「オーバーライド」することは可能ですが、これを行うコードは、クラスのメソッドをオーバーライドするコードよりも明らかに疑わしいものです。
そうじゃない?
>>> "abc".__len__()
3
len
。彼らは人々に強制する.__len__
よりも人々に強制するほうが簡単だと考えています.len()
。その同じこと、そして1つははるかにきれいに見えます。言語にOOPが含まれる場合、__len__
世界で何を作成するかlen(..)