見出し画像

【Python】呼び出し可能オブジェクト

FastAPIのDepends周りでエラー(AttributeError)にハマったが、そもそもDepends()と関数、関数オブジェクト、呼び出し可能(不能)についての理解が曖昧だったため、わかる範囲で、まとめていく

呼び出し可能オブジェクト

クラスを定義したり、関数を定義したりすると、それらはかっこ「()」を付加し、そこ中に引数を指定することで、「呼び出す」ことができるようになる。こうしたオブジェクトのことを「呼び出し可能オブジェクト」と呼ぶ。

 Pythonでは通常、クラスは呼び出し可能オブジェクトだが、そのインスタンスは呼び出し可能ではない。しかし、インスタンスを呼び出し可能オブジェクトのようにもできる。これには__call__特殊メソッドを定義すればよい。

引用:呼び出し可能オブジェクト

依存関係

依存関係が関数として宣言されているのを見てきました。しかし、依存関係を宣言する唯一の方法ではありません(おそらくその方が一般的でしょうが)。重要なのは、依存関係は "callable "でなければならないということです。
Pythonにおける "callable "とは、Pythonが関数のように "呼び出せる "ものを指します。つまり、(関数ではないかもしれませんが)何かのオブジェクトを持っていて、それを「呼び出せる」(実行できる) ことである。

引用:依存関係を作るものは何か

Dependsと関数呼び出しとの違いなども随時追記予定

Depends()のソースコード

class Depends:
   def __init__(
       self, dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True
   ):
       self.dependency = dependency
       self.use_cache = use_cache

公式ソースコード:fastapi/fastapi/params.py 

追記_20220608

Pythonの事例ではないけれど、関数名やクラス名のみで指定する時は、それはその(関数やクラス)オブジェクト自体ではなく、その関数やクラスが格納されているアドレス情報(「ポインタ」、「参照」)を指定していることになる、というようなイメージかな??
変数やdictの上書きとかで、値渡し、参照渡しの場面では注意してたけど、関数やクラスの呼び出しで「()なし」なんてあんまり考えたことなかったから良い勉強になりました。

enumerate()で、関数名を利用したい時に、「()なし」での指定などがあるが、そのうちその辺りの関連ももう少し掘り下げてみていきたい。。。

https://dixq.net/forum/viewtopic.php?t=17750


Pythonにおいて呼び出す対象は、関数だったり、クラス(などのオブジェクト)だったりするわけだが、公式ドキュメントによると、呼び出しとは、

6.3.4. 呼び出し (call)
呼び出しは、呼び出し可能オブジェクト (例えば function) を arguments の系列とともに呼び出します。系列は空の系列であってもかまいません:

https://docs.python.org/ja/3/reference/expressions.html#calls

というわけで、呼び出し可能なオブジェクトと「()」によって(0個以上の)引数の系列とともに呼び出すことが仕様となっている。
※では、「呼び出し可能オブジェクト」、「呼び出し不能」、「呼び出し」とは、という点は現状、私の力不足で、公式ドキュメントから発見できていない。。。

この記事が気に入ったらサポートをしてみませんか?