2008-09-17 6 views
18

例:はなぜPythonで辞書やリストによって継承「lenは」関数ではありません

a_list = [1, 2, 3] 
a_list.len() # doesn't work 
len(a_list) # works 

のPythonいる(非常に)オブジェクトの最大len '関数がない理由、私は理解していない指向オブジェクトによって継承されます。 プラス私は間違った解決策を試しています。それは私にとって論理的なものです。

+0

機能は継承されません。方法は次のとおりです。どのオブジェクトの 'len'メソッドから継承したいのですか? – tzot

+0

lenは__len__メソッドを呼び出すだけなので、これは無関係なので、同じ継承の問題は引き続き適用されます。 –

+5

@Eliあなたは '__len__'メソッドを意味します - SOは二重下線を太字として解釈しました。 =) – MatrixFrog

答えて

40

グイドの説明はhereです:

まず第一に、私はHCIの理由のために)(x.len上(x)のlenを選んだ()DEF __len __は(かなり後になりました)。実際には2つの絡み合った理由があります:

(a)いくつかの操作では、プレフィックス表記はpostfix - prefix(およびinfix!)操作よりも読みやすく、数学では伝統的な意味を持ちます。問題についての数学者の考え方。 x *(a + b)のような公式をxa + xbに書き直した簡単なことを、生のOO表記を使って同じことをやっていることのうわさに比べてください。

(b)len(x)というコードを読むと、何かの長さを求めていることがわかります。これは2つのことを私に伝えます:結果は整数で、引数はある種のコンテナです。逆に、私がx.len()を読むと、xが標準のlen()を持つクラスから継承したり、ある種のコンテナとしてインタフェースを実装していることがわかっています。マッピングを実装していないクラスがget()またはkeys()メソッドを持っているか、またはファイルではないものがwrite()メソッドを持っているときに、時々混乱することがあります。

同じことを別の言い方をすると、組み込み操作として 'len'が表示されます。私はそれを失うことが嫌いです。/.../

+22

知らない人のために、HCIはHuman-Computer Interfaceの略です。だから、Guidoが "HCI理由"の決定を下したと彼は言っています。 –

+0

@Thomas:Pythonは、Cと同じようにビットごとのORに '|'を使います。 – dan04

+1

Guidoが汎用関数を主張しているのはメソッドよりも優れています。心が不安になる:/ –

2

多分あなたは__len__を探しています。そのメソッドが存在する場合、len(a)は次のように呼び出します。

>>> class Spam: 
... def __len__(self): return 3 
... 
>>> s = Spam() 
>>> len(s) 
3 
10

それだけではありません。

あなたがすることができますが、しかし、実行します。

>>> [1,2,3].__len__() 

3 

はクラスに__len__()メソッドを追加すると、len()魔法の仕事を作るものです。

2

まあ、実際の長さの方法があり、ちょうど隠されている:

>>> a_list = [1, 2, 3] 
>>> a_list.__len__() 
3 

LENを()組み込み関数は、単にlenは隠さへの呼び出しのラッパーであるように思われます()オブジェクトのメソッド。

なぜ彼らがこのように物事を実装する決定を下したのか分かりません。

11

短い答え:1)下位互換性と2)それは本当に重要な違いがありません。詳細な説明は、を参照してください。

このような操作に対する慣用的なPythonのアプローチは、直接呼び出されることを意図しない特殊な方法です。たとえば、自分のクラスでx + yを動作させるには、__add__メソッドを記述します。int(spam)がカスタムクラスを正しく変換するようにするには、__int__メソッドを記述します。 len(foo)が賢明であることを確認するには、__len__メソッドを書いてください。

これは、常にPythonにあったことであり、いくつかの点ではそれが意味をなさないと思います。特に、これはオペレータのオーバーロードを実現するための賢明な方法のようです。残りの部分については、異なる言語には同意しない。 Rubyではint(spam)の代わりにspam.to_iを直接呼び出して何かを整数に変換します。

Pythonは非常にオブジェクト指向の言語であり、オブジェクトの長さを取得するために外部関数を呼び出さなければならないというのは間違いです。一方、len(silly_walks)は、silly_walks.len()より煩わしくなく、Guidoは実際には(http://mail.python.org/pipermail/python-3000/2006-November/004643.html)が好きだと言っています。

+3

ああ...これは最終的にそれのすべての意味を作った。 len()は実際に関数である演算子のほうが多いです。 – Nate

5

この方法は、言語の残りの部分とうまく適合します。 Pythonの規約では、特殊なメソッドを__foo__という特殊メソッドに追加して、(特定の基本クラスから派生するのではなく)特定の機能を持たせることです。それは反復可能__call__方法

  • を有する場合、それは__iter__方法を持っている場合、それは__getitem____setitem__を有する場合、例えば、オブジェクトが

    • 呼び出し可能であり、
    • は[]とのアクセスをサポートします。これらの特別なメソッドの
    • ...

    一つは、それがlen()でアクセスの長さを持っています__len__です。