python
1class A(B):
2 pass
class文の引数は親クラスの指定に使います。↑は「AはBを継承する」という宣言です。
関数の引数は呼び出し元からの値に名前を束縛するのに使います。要するにローカル変数です。
機能がぜんぜん違います。
下記のサンプルコードの実行結果にあるようにクラスの第一引数に書いてるself, object, cls, typeは、全て同じ機能をもっていると理解しています。
上記の通り、そんなことはないです。
第一引数に取るのは、クラスオブジェクトの基底クラスとなるtypeクラスを継承するために何かしらの引数名を書く必要があると理解しています。
必要はないです。書かれていない場合はobjectを継承します。
その必要性は、classと定義することでメタクラスを継承するように強制されると理解しています。
意味が通じませんでした。
とりわけ、typeとobjectは、いつ利用するかが気になっています。
typeはPython言語の組み込みクラスと同じ名前なので、慣習としてローカル変数名には使いません。
(追記2)
関数の話をします。
python
1def a(x, y):
2 pass
と宣言すると、まず「引数が2つの関数オブジェクト」が作られます。そしてdef文が実行された名前空間でa
という名前を束縛します(つまり、変数a
に代入されるということです)。
この関数オブジェクトは2つの引数を受け取ります。
関数が呼び出された時に作られる、関数の本体スイート(ブロックの中)を実行している時だけ存在する名前空間があります。
その名前空間に束縛される名前のことをローカル変数と呼んでいます。
関数をa(4, 8)
というコードを実行すると、名前a
が解決されてオブジェクトが取り出されます(それは関数オブジェクトでした)。
そのオブジェクトを"4と8という2つの引数を伴って呼び出す"という操作がおこなわれます。
関数オブジェクトの呼び出しがおこなわれると、
まず名前空間が作られ、
関数の第1引数である名前x
が、呼び出しの第1引数である4に束縛され、
関数の第2引数である名前y
が、呼び出しの第2引数である8に束縛されます。
そののち本体が実行されます。
本体を実行している間は実行時の名前空間に名前x
とy
が束縛されています。
ですから定義からしてx
とy
はローカル変数です。
ここで、"引数"という言葉が2種類の対照的な意味で登場していました。
紛らわしいので、
関数側の引数を[仮引数 とか parameter]((https://docs.python.org/ja/3/glossary.html#term-parameter)と呼び、
呼び出し時に渡す引数を実引数 とか argumentと呼んで区別したりしますね。
(追記)
メソッドの話をします。
公式ドキュメントのこのあたりです。
https://docs.python.org/ja/3/reference/datamodel.html?highlight=new#index-36
ちょっと読み進めたところに
インスタンスメソッドオブジェクトが呼び出される際、根底にある関数 (__func__
) が呼び出されます。このとき、クラスインスタンス (__self__
) が引数リストの先頭に挿入されます。例えば、 C
を関数 f()
の定義を含むクラス、 x
を C
のインスタンスとすると、 x.f(1)
の呼び出しは C.f(x, 1)
の呼び出しと同じです。
とでてきます。
python
1class C:
2 def f(self, i):
3 pass
とすると、class文の本体スイートが実行されクラスオブジェクトが作られます。
そしてclass文が実行された名前空間でC
という名前を束縛します(つまり、変数C
に代入されるということです)。
クラスオブジェクトが作られた時にそのf
という属性は、def文で作成された「引数が2つの関数オブジェクト」に束縛されています。
C.f
と参照すると「引数が2つの関数オブジェクト」を指しているというわけです。
とインスタンス化して、
と呼び出すとき、その呼び出しはC.f(x, 1)
の呼び出しと同じだと言っています。
実は、x.f
は、def文で生成された(C.f
で参照できる)関数とは別のオブジェクトに束縛されています。
インスタンスメソッドオブジェクトなるものに束縛されていると説明されていて、そのインスタンスメソッドオブジェクトを(1)
という引数で呼び出すとその中でC.f(x, 1)
の呼び出しがおこなわれるわけです。
(そのような機能を持っているオブジェクトに対して、"インスタンスメソッドオブジェクト"という名前を付けた、という理解でもいいかもしれません)
前述の通り、C.f
はdef f(self, i): pass
で作成された関数オブジェクトでした。
C.f(x, 1)
の呼び出しがおこなわれるということは、
その関数の第1引数である名前self
は、メソッドの呼び出し元であるx
に束縛され、
その関数の第2引数である名前i
は、メソッド呼び出しの第1引数である1
に束縛されます。
「selfには自分自身が入る」などとよく説明されますが、その機構は上記のようになっています。
続けて
クラスメソッドオブジェクトからインスタンスメソッドオブジェクトが導出される際、 __self__
に記憶されている "クラスインスタンス" は実際はクラスそのものなので、 x.f(1)
や C.f(1)
の呼び出しは、根底にある関数を f
として f(C,1)
の呼び出しと等価です。
と書いてあります。
python
1class C:
2 @classmethod
3 def f(cls, i):
4 pass
5
6x = C()
に対してC.f(1)
やx.f(1)
と呼び出しするとき、
その呼び出しは、根底の関数オブジェクトをf
とするとf(C, 1)
の呼び出しと同じだと言っています。
関数の第1引数である名前cls
は、メソッドの呼び出し元(のクラス)であるC
に束縛され、
関数の第2引数である名前i
は、メソッドの第1引数である1
に束縛されます。
https://docs.python.org/ja/3/reference/datamodel.html#object.new
に
このメソッドは特別扱いされているので、明示的に静的メソッドと宣言する必要はありません
と記載されている通り、__new__
は明に書かなくても静的なメソッド(≒クラスメソッド)として扱われることになっています。