質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

2698閲覧

pythonのクラスのインスタンス化したときの挙動とインスタンス化方法について

sequelanonymous

総合スコア123

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

5クリップ

投稿2021/04/20 14:31

上記、タイトルのことを確認しています。
下記のサンプルコードを一つずつ挙動確認しながら理解できないことを書いていきました。なにかお気づきの点がありましたらご教示いただけませんでしょうか?

サンプルコード singleton.py

python

1class SpecialMethods: 2 print("class variable") 3 4 def __init__(self): 5 print(f"__init__: {self}") 6 7 def __new__(cls): 8 self = super().__new__(cls) 9 print(f"cls of __new__: {cls}") 10 print(f"self of __new__: {self}") 11 return self 12 13 def __call__(self): 14 print(f"__call__: {self}") 15 16 def _type(type): 17 print(f"type: {type}") 18 19 def _self(self): 20 print(f"self: {self}") 21 return type(self) 22 23 def _cls(cls): 24 print(f"cls: {cls}") 25 return type(cls)

コンソール

>>> from singleton import SpecialMethods class variable

1)なぜ、importした瞬間にprint文の出力がでるのでしょうか?

>>> sm = SpecialMethods >>> sm() cls of __new__: <class 'singleton.SpecialMethods'> self of __new__: <singleton.SpecialMethods object at 0x10d304f40> __init__: <singleton.SpecialMethods object at 0x10d304f40> <singleton.SpecialMethods object at 0x10d304f40> >>> type(sm) <class 'type'> >>>

2)通常であれば、sm = SpecialMethods()のように括弧付きで変数にいれることでクラスのインスタンス化ができるはずですが、かっこなしで変数にいれたあとにカッコつけることでインスタンス化することができるのでしょうか?
3)また、その場合、かっこなしでのsm及びSpecialMethodsは、なにものなんでしょうか?クラスオブジェクトといえばいいでしょうか?また、そのクラスオブジェクトの型が<class 'type'>になっていって、これは何を指しているのでしょうか?

>>> sm_fn = SpecialMethods() cls of __new__: <class 'singleton.SpecialMethods'> self of __new__: <singleton.SpecialMethods object at 0x10d304f40> __init__: <singleton.SpecialMethods object at 0x10d304f40> >>> sm_fn._type() type: <singleton.SpecialMethods object at 0x10d304f40> >>> sm_fn._self() self: <singleton.SpecialMethods object at 0x10d304f40> <class 'singleton.SpecialMethods'> >>> sm_fn._cls() cls: <singleton.SpecialMethods object at 0x10d304f40> <class 'singleton.SpecialMethods'>

4)<class 'singleton.SpecialMethods'>は、type()でかえってきた型のはずですが、型名でもなくただのクラス名を返しています。これは何を意味しているのでしょうか?

上記と同じコードを下記のようにpythonコマンドを実行した場合

python

1... 2... 3... 4if __name__ == '__main__': 5 6 ss = SpecialMethods() 7 print(ss()) 8 print(ss) 9 print(ss._type()) 10 print(ss._self()) 11 print(ss._cls()) 12
$ python singleton.py class variable cls of __new__: <class '__main__.SpecialMethods'> self of __new__: <__main__.SpecialMethods object at 0x108bf8f70> __init__: <__main__.SpecialMethods object at 0x108bf8f70> __call__: <__main__.SpecialMethods object at 0x108bf8f70> None <__main__.SpecialMethods object at 0x108bf8f70> type: <__main__.SpecialMethods object at 0x108bf8f70> None self: <__main__.SpecialMethods object at 0x108bf8f70> <class '__main__.SpecialMethods'> cls: <__main__.SpecialMethods object at 0x108bf8f70> <class '__main__.SpecialMethods'>

5)インスタンス化した場合は、typeの結果が__main__.となりますが、<class 'main.SpecialMethods'>の部分の、main.は何を指していてい、なぜでてくるのでしょうか?

Taste_Bitter👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

以下の説明を理解するためには、かなりの知識が必要です。
分からないとところはネットで調べるか、質問して下さい。

  • 1)なぜ、importした瞬間にprint文の出力がでるのでしょうか?

from singleton import SpecialMethodsを実行するとsingleton.pyがimportされているかどうかを確認し、importされていなければsingleton.pyをインポートして、SpecialMethodsという変数にsingleton.SpecialMethodsをバインドします。
singleton.pyがimportされるとき、SpecialMethodsのクラス定義が実行されます。クラス定義の中のコードは、名前空間をクラスSpecialMethodsとして実行されます。ここで、print("class variable")が実行されるのでclass variableが印字されます。
もし、もう一度from singleton import SpecialMethodsを実行した場合は、既にインポート済みなので、print("class variable")が実行されません。

  • 2)通常であれば、sm = SpecialMethods()のように括弧付きで変数にいれることでクラスのインスタンス化ができるはずですが、かっこなしで変数にいれたあとにカッコつけることでインスタンス化することができるのでしょうか?

Pythonの変数は、文字列とオブエジェクトのバインドです。
SpecialMethodsという変数は、クラスそのものではなく、そのクラスとバインドされている文字列です。sm = SpecialMethods は、"sm"という文字列を”SpecialMethods”という文字列にバインドされているオブジェクト(この場合にはクラスオブジェクト)をバインドしただけです。
SpecialMethods()は文字列"SpecialMethod”にバインドされているクラスオブジェクトのインスタンスを作成するという処理であり、変数名とは関係ありません。したがって、sm = SpecialMethodsを実行した後であれば、sm()でも同じことが起こります。

  • 3)また、その場合、かっこなしでのsm及びSpecialMethodsは、なにものなんでしょうか?クラスオブジェクトといえばいいでしょうか?

はい。そうです。

  • また、そのクラスオブジェクトの型が<class 'type'>になっていって、これは何を指しているのでしょうか?

typeはクラスのクラスです。メタクラスとも呼びます。
pythonの全てのクラスはtypeまたはtypeの派生クラスのインスタンスです。

  • 4)<class 'singleton.SpecialMethods'>は、type()でかえってきた型のはずですが、型名でもなくただのクラス名を返しています。これは何を意味しているのでしょうか?

pythonでは、クラスと型は同じ意味です。従って型名とクラス名は同じです。

  • 5)インスタンス化した場合は、typeの結果がmain.となりますが、<class 'main.SpecialMethods'>の部分の、main.は何を指していてい、なぜでてくるのでしょうか?

explanation

1$ python singleton.py 2として起動した場合、モジュール名は__main__となります。 3<class '__main__.SpecialMethods'>は__main__のSpecialMethodsというクラスを表示したものです。

投稿2021/04/20 15:57

ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sequelanonymous

2021/04/21 04:04

ご回答ありがとうございます!一点ご確認させてください。 ご回答のなかで頻繁に言及されてるバインドとはどういう意味でしょうか? なんとなく雰囲気では理解しましたが、より具体的にどういう処理のことをバインドと解釈したらよろしいでしょうか? > Pythonの変数は、文字列とオブエジェクトのバインドです。 また、文字列(str)もオブジェクトですし、ここでいうオブジェクトは、なんのことを言っていますでしょうか?
ppaul

2021/04/21 07:57

bindとはヒモで縛るというような意味です。日本語の公式ドキュメントでは束縛と訳していますね。 https://docs.python.org/ja/3/reference/executionmodel.html?highlight=%E6%9D%9F%E7%B8%9B#naming-and-binding をご覧ください。 実装上は辞書を使って行うことが多いですが、python処理系によって違っても良いことになっています。 普通のグローバル変数の変数名と値のバインドはglobals()が返す辞書で行っています。
sequelanonymous

2021/04/21 17:52

ありがとうございます!ドキュメント読んで理解できました!
guest

0

  • 1

クラスのスイートは実行されるからです。

次にクラスのスイートが、新たな実行フレーム (名前づけと束縛 (naming and binding) を参照してください) 内で、新たに作られたローカル名前空間と元々のグローバル名前空間を使って実行されます (通常、このスイートには主に関数定義が含まれます)。
8. 複合文 (compound statement) — Python 3.9.4 ドキュメント

  • 2

できます。

  • 3

リファレンスに準拠するのであれば、クラスオブジェクトないし型オブジェクトで良いと思います。また、クラスオブジェクトはtypeクラスのインスタンスです

次に、継承リストを基底クラスに、保存されたローカル名前空間を属性値辞書に、それぞれ使ってクラスオブジェクトが生成されます。最後に、もとのローカル名前空間において、クラス名がこのクラスオブジェクトに束縛されます。
8. 複合文 (compound statement) — Python 3.9.4 ドキュメント

  • 4

Pythonのオブジェクト指向においては原則的には型=クラスです。

引数が1つだけの場合、object の型を返します。返り値は型オブジェクトで、一般に object.class によって返されるのと同じオブジェクトです。
組み込み関数 — Python 3.9.4 ドキュメント | type

  • 5

まず型オブジェクトはreprによって文字列化されているのが前提です。

この関数は多くの型について、 eval() に渡されたときと同じ値を持つようなオブジェクトを表す文字列を生成しようとします。そうでない場合は、山括弧に囲まれたオブジェクトの型の名前と追加の情報 (大抵の場合はオブジェクトの名前とアドレスを含みます) を返します。
組み込み関数 — Python 3.9.4 ドキュメント | repr

__main__はトップレベルモジュールですね。

main --- トップレベルのスクリプト環境 — Python 3.9.4 ドキュメント

山括弧で囲まれた中には、アドレスが表示されています。__main__は所属する名前空間ということになります。


真面目にPythonの言語仕様を勉強することが目的であれば、リファレンスの以下の項の通読をおすすめします。

「はじめに」から「組み込み例外」まで。

「プログラミング FAQ」と「デザインと歴史 FAQ」の二つ。

通読まではしないとしても、言語仕様や組み込み関数・型の挙動等でわからないことがあったらこの辺りを確認する癖をつけると良いと思います。だいたいのことは書いてあります。

また、こちらのサイトもおすすめしておきます。

投稿2021/04/20 15:35

hayataka2049

総合スコア30935

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sequelanonymous

2021/04/21 17:55

ありがとうございます!ここで言われてる型オブジェクトとは、具体的に何を指していますでしょうか?
guest

0

解決済みのようですが、少しだけ補足です。

質問文にある、実行されるクラスのコードは以下の通りになってます。

python

1class SpecialMethods: 2 # (省略) 3 def _type(type): 4 print(f"type: {type}") 5 6 def _self(self): 7 print(f"self: {self}") 8 return type(self) 9 10 def _cls(cls): 11 print(f"cls: {cls}") 12 return type(cls)

ソースコードで「_type()」「_self()」「_cls()」はどれもメソッドの第一引数をprint文で表示しています。インスタンスメソッドでは、第一引数にはクラスインスタンスが渡されます(@classmethodデコレータを使った場合など、違う状況もありますが)。第一引数名を「type」「self」「cls」の何にしたところで変わりません。

なお、慣例的にインスタンスメソッドでは「self」、クラスメソッドでは「cls」を第一引数名に使うことが多いようです。

3. データモデル - Python 3.9.4 ドキュメントには以下のように説明されています。

インスタンスメソッドオブジェクトが呼び出される際、根底にある関数 (func) が呼び出されます。このとき、クラスインスタンス (self) が引数リストの先頭に挿入されます。例えば、 C を関数 f() の定義を含むクラス、 x を C のインスタンスとすると、 x.f(1) の呼び出しは C.f(x, 1) の呼び出しと同じです。

インスタンスメソッドで、インスタンス、クラスを使い分けたいときは、第一引数の名前を変えるのではなく、第一引数の属性などを使ってアクセスしてください。以下、簡単な例です。

python

1>>> class c1(): 2... def f1(self): 3... print("self: {}".format(self)) 4... print("type(self): {}".format(type(self))) 5... print("self.__class__: {}".format(self.__class__)) 6... @classmethod 7... def f2(cls): 8... print("classmethod cls: {}".format(cls)) 9... 10>>> 11>>> 12>>> 13>>> ins1 = c1() 14>>> ins1.f1() 15self: <__main__.c1 object at 0x7fa43f39e048> 16type(self): <class '__main__.c1'> 17self.__class__: <class '__main__.c1'> 18>>> ins1.f2() 19classmethod cls: <class '__main__.c1'> 20>>>

投稿2021/04/22 00:13

msiz07

総合スコア172

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sequelanonymous

2021/04/23 14:05

コメントありがとうございます!すみません、下記の違いがわからないのですが、呼び出し方にどんな違いがありますでしょうか? >>> ins1.f1() self: <__main__.c1 object at 0x7fa43f39e048> type(self): <class '__main__.c1'> self.__class__: <class '__main__.c1'> >>> ins1.f2() classmethod cls: <class '__main__.c1'> >>>
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問