[解決済み] なぜPythonのクラスでは__init__を使うのですか?
疑問点
クラスの初期化について、理解するのに苦労しています。
クラスは何のためにあるのでしょうか、また、クラスに何を含めるべきかをどのように判断すればよいのでしょうか。クラスで書くには、関数を作るのとは違ったタイプの考え方が必要なのでしょうか (関数を作って、それを再利用できるようにクラスでラップすればいいと思いました。それはうまくいくでしょうか?)
以下はその例です。
class crawler:
# Initialize the crawler with the name of database
def __init__(self,dbname):
self.con=sqlite.connect(dbname)
def __del__(self):
self.con.close()
def dbcommit(self):
self.con.commit()
あるいは別のコードサンプル。
class bicluster:
def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
self.left=left
self.right=right
self.vec=vec
self.id=id
self.distance=distance
を持つクラスは非常に多くあります。
__init__
他の人のコードを読もうとすると出会うのですが、それを作るロジックが理解できません。
どのように解決するのですか?
あなたの書いたものでは、クラスとオブジェクトの違いという重要な理解が欠けています。
__init__
はクラスを初期化するのではなく、クラスやオブジェクトのインスタンスを初期化するのです。それぞれの犬には色がありますが、クラスとしての犬には色はありません。それぞれの犬は4本以下の足を持っているが、犬のクラスは持っていない。クラスはオブジェクトの概念である。ファイドーとスポットを見たとき、あなたは彼らの類似性、犬らしさを認識する。それがクラスです。
というとき
class Dog:
def __init__(self, legs, colour):
self.legs = legs
self.colour = colour
fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")
ファイドーは4本足の茶色い犬で、スポットはちょっと不自由でほとんど黄色い犬ということですね。その
__init__
関数はコンストラクタ、またはイニシャライザと呼ばれ、クラスの新しいインスタンスを作成するときに自動的に呼び出されます。その関数の中で、新しく生成されたオブジェクトは、パラメータ
self
. この表記は
self.legs
という属性は
legs
というオブジェクトの属性で、変数
self
. 属性は変数のようなものですが、オブジェクトの状態や、オブジェクトが利用できる特定のアクション(関数)を記述します。
しかし
colour
を設定しないことに注意してください。これは抽象的な概念です。クラスに対して意味のある属性もあります。例えば
population_size
はそのひとつです。Fidoは常にひとつなので、Fidoを数えることは意味をなしません。しかし、犬を数えるのは意味があります。世界に2億匹の犬がいるとしましょう。これはDogクラスのプロパティです。ファイドーは2億という数字には関係ないし、スポットも関係ない。これはクラス属性と呼ばれるもので、インスタンス属性と呼ばれるものは
colour
とか
legs
の上にあります。
さて、イヌっぽくない、プログラミングに関連した話です。以下に書くように、物事を追加するクラスは賢明ではありません - それは何のクラスなのでしょうか?Pythonのクラスは、同じような振る舞いをする異なるデータの集まりを構成します。犬のクラスは、FidoとSpotと19999999998匹の似たような動物で構成され、全員が街灯におしっこをしています。モノを追加するクラスは何から構成されているのだろうか?それらは固有のどのようなデータによって異なるのだろうか?また、どのような動作が共通しているのでしょうか?
しかし、数というのは...もっと面白いテーマです。例えば、整数。犬よりずっとたくさんあるんだ。Pythonがすでに整数を持っていることは知っていますが、(Pythonの整数をズルして)もう一度実装して遊んでみましょう。
というわけで、整数はクラスです。いくつかのデータ(値)と、いくつかの動作("私をこの他の数に加える")を持っています。これを示してみましょう。
class MyInteger:
def __init__(self, newvalue):
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
def add(self, other):
# when an integer wants to add itself to another integer,
# we'll take their values and add them together,
# then make a new integer with the result value.
return MyInteger(self.value + other.value)
three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8
これはちょっと壊れやすいですね(仮に
other
はMyIntegerであると仮定しています)、今は無視しましょう。実際のコードでは、そうしません。念のためにテストして、もしかしたら強制することもあるかもしれません ("you're not an integer? by golly, you have 10 nanoseconds to become one !")。9... 8... ")。
分数を定義することもできます。分数は足し算もできるのです。
class MyFraction:
def __init__(self, newnumerator, newdenominator):
self.numerator = newnumerator
self.denominator = newdenominator
# because every fraction is described by these two things
def add(self, other):
newdenominator = self.denominator * other.denominator
newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
return MyFraction(newnumerator, newdenominator)
分数は整数よりさらに多い(実際は違うが、コンピュータはそんなこと知らない)。2つ作ってみましょう。
half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6
ここでは実際に何かを宣言しているわけではありません。属性は新しい種類の変数のようなものです。通常の変数は一つの値しか持ちません。例えば、あなたが
colour = "grey"
. という名前の別の変数を持つことはできません。
colour
という名前の変数を持つことはできません。
"fuchsia"
- がコード内の同じ場所にない
配列はそれをある程度解決してくれます。もしあなたが
colour = ["grey", "fuchsia"]
とすると、変数に2つの色を積み重ねたことになりますが、その位置(この場合は0か1か)で区別しています。
属性はオブジェクトに束縛される変数です。配列と同じように、たくさんの
colour
という変数があります。
を持つことができます。
. だから
fido.colour
は一つの変数ですが
spot.colour
は別のものです。最初のものは変数内のオブジェクトに束縛されている
fido
であり、2番目は
spot
. さて、あなたが
Dog(4, "brown")
を呼び出したとき、あるいは
three.add(five)
を使用した場合、常に目に見えないパラメータが存在し、それがパラメータリストの先頭にあるぶら下がった余分なパラメータに割り当てられます。これは慣例的に
self
と呼ばれ、ドットの前にあるオブジェクトの値を取得します。したがって、Dogの
__init__
(コンストラクタ)に
self
は新しい Dog がどのようなものであっても構いません。
MyInteger
's
add
,
self
はオブジェクトにバインドされ、変数
three
. このように
three.value
の外側では同じ変数になります。
add
と同じになります。
self.value
の中で
add
.
もし私が
the_mangy_one = fido
というオブジェクトを参照し始めます。
fido
として知られているオブジェクトを、さらに別の名前で呼ぶことにします。これからは
fido.colour
とは全く同じ変数で
the_mangy_one.colour
.
ということは
__init__
. これらは、Dogの出生証明書にいろいろと書き込んでいると考えてよいでしょう。
colour
はそれ自体がランダムな変数で、何でも入れることができます。
fido.colour
または
self.colour
はDogのIDシートのフォームフィールドのようなもので、そして
__init__
は、店員が初めてそれを記入するところです。
もっとわかりやすいのは?
EDIT : 下のコメントを展開します。
のリストということですね。 オブジェクトのリストです。 という意味ですよね?
まず最初に
fido
は実はオブジェクトではありません。これは変数であり、現在オブジェクトを含んでいます。
x = 5
,
x
は現在数字の5を含む変数です。後で気が変わったら、次のようにします。
fido = Cat(4, "pleasing")
とすることができます (ただし、クラス
Cat
)、そして
fido
はそれ以降、猫オブジェクトを含むようになります。もし
fido = x
とすると、数字の5が含まれ、動物のオブジェクトは含まれません。
クラスはそれ自体では、特にインスタンスを追跡するコードを書かない限り、そのインスタンスを知ることはできません。例えば
class Cat:
census = [] #define census array
def __init__(self, legs, colour):
self.colour = colour
self.legs = legs
Cat.census.append(self)
ここで
census
はクラスレベルの属性で
Cat
クラスのクラスレベル属性です。
fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that
を得ることができないことに注意してください。
[fluffy, sparky]
. これらは単なる変数名である。もし猫自体に名前を付けたいのであれば、名前用の属性を別に作り、その上で
__str__
メソッドをオーバーライドしてこの名前を返さなければならない。このメソッドの(つまりクラス結合関数で、ちょうど
add
または
__init__
) の目的は、印刷するときのように、オブジェクトを文字列に変換する方法を記述することです。
関連
-
Evidentlyを用いたPythonデータマイニングによる機械学習モデルダッシュボードの作成
-
[解決済み】お使いのCPUは、このTensorFlowバイナリが使用するようにコンパイルされていない命令をサポートしています。AVX AVX2
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] __init__.py は何のためにあるのですか?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] Pythonで静的なクラス変数は可能ですか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ピロウズ画像色処理の具体的な活用方法
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
python implement mysql add delete check change サンプルコード
-
Python百行で韓服サークルの画像クロールを実現する
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】pygame.error: ビデオシステムが初期化されていない
-
[解決済み】TypeError: 系列を <class 'float'> に変換することができません。
-
[解決済み] 'int'オブジェクトに'__getitem__'属性がない。
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。