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()
とエラーをスローすると、エラーメッセージはより正確になりますが、これは非常に狂ったケースであり、非常に頻繁に起こるとは思わないでしょう。
レイモンドがそのコードを書いたときに考えていたことを本当に知るためには、彼に尋ねなければならないと思います(あるいは、コミットの履歴で突き進み、コミットメッセージでそれを言いたいと思います)。
記録のために、このデザインを持つ唯一の理由は、 '__init__ 'の' self'インスタンスを誤って置き換えずに 'self'という名前のキーワード引数で' Counter'を初期化できるようにすることです。位置的な可変引数を受け入れ、手動で "実際の" 'self 'を抽出しなければならなかったので、キーワードの引数で上書きできる外部名はありませんでした。 '__init__'を手動で呼び出すのでなければ、実際にこのエラーを引き起こすことはできません(サブクラスで' super'を使わずに、そうすることで暗黙的に渡すことができます)。 – ShadowRanger