2016-01-27 7 views
6

私はカウンタークラスの__init__メソッドを読んで、これは見た:なぜCounterの__init__メソッドがディスクリプタと呼ばれていますか?

if not args: 
    TypeError("descriptor '__init__' of 'Counter' object " 
       "needs an argument") 

私はそれが記述子によって何を意味するのかわからなかったので、私はPythonのデータモデルドキュメントをチェックして、この発見:

一般に、記述子は、属性アクセスが記述子プロトコルのメソッド、つまり__get __()、__set __()、および__delete __()によってオーバーライドされた「バインディング動作」を持つオブジェクト属性です。これらのメソッドのいずれかがオブジェクトに対して定義されている場合、それは記述子であると言われます。

これらのメソッドはどれもクラス定義に存在しないようですが、なぜ__init_はディスクリプタと呼ばれていますか?

+0

記録のために、このデザインを持つ唯一の理由は、 '__init__ 'の' self'インスタンスを誤って置き換えずに 'self'という名前のキーワード引数で' Counter'を初期化できるようにすることです。位置的な可変引数を受け入れ、手動で "実際の" 'self 'を抽出しなければならなかったので、キーワードの引数で上書きできる外部名はありませんでした。 '__init__'を手動で呼び出すのでなければ、実際にこのエラーを引き起こすことはできません(サブクラスで' super'を使わずに、そうすることで暗黙的に渡すことができます)。 – ShadowRanger

答えて

4

Pythonでは、すべての関数は、(__init__を含む)記述子です。これは実際に彼らがどのようなものを知っているのかです。selfはクラスで使用されています。例えば、私は、関数(foo)を定義することができ、私はそれのメソッドを見ると、その後、私はfooはそれが記述プロトコルに準拠します__get__方法を持っていることがわかります:

>>> def foo(): 
... pass 
... 
>>> dir(foo) 
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] 
>>> '__get__' in dir(foo) 
True 

ので、専門用語が使用さ少なくともの正確ながあります。

私はそれをディスクリプタの代わりに「バウンドメソッド」と呼んでいるかもしれませんが、python3.xでは、通常の関数、バインドされたメソッド、およびアンバインドされたメソッドの区別があります。もう少し泥だらけになり(未結合の方法はpython3.xで定期的な機能です)...もちろん


、私は

...私 Counterサブクラスを初期化するために、ディスクリプタの異なるタイプを使用することができます
class MyDescriptor(object): 
    def __get__(self, inst, cls): 
     # This is a really useless descriptor! 
     return Counter.__init__.__get__(inst, cls) 

class MyCounter(Counter): 
    __init__ = MyDescriptor() 

とエラーをスローすると、エラーメッセージはより正確になりますが、これは非常に狂ったケースであり、非常に頻繁に起こるとは思わないでしょう。

レイモンドがそのコードを書いたときに考えていたことを本当に知るためには、彼に尋ねなければならないと思います(あるいは、コミットの履歴で突き進み、コミットメッセージでそれを言いたいと思います)。

+0

私はあなたの答えを理解していないと私はそれが引用されたドキュメントに沿ってどのように落ちるか分からない。あなたは詳細を教えていただけますか? – timgeb

+0

ああ、カウンタではなく\ _ \ _ get__を定義した関数であることを忘れてしまった。ありがとう。 –

+0

関連:関数を単に関数と呼ぶだけで、説明的な意味を持たない記述子(関数の意味はありません)を記述子と呼ぶのはなぜですか? –

関連する問題