クラスの初期化を理解できません。
それらのポイントは何ですか?また、それらに何を含めるべきかをどのように知るのですか?クラスでの記述には、関数の作成と関数の作成とでは異なる考え方が必要ですか(関数を作成し、クラスにラップして再利用できると考えました。それは機能しますか?)
以下に例を示します。
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足以下ですが、犬のクラスにはありません。クラスはオブジェクトの概念です。 FidoとSpotを見ると、それらの類似点、つまり犬のように見えます。それがクラスです。
あなたが言う時
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は常に1であるため、Fidoを数えることは意味がありません。犬を数えるのは理にかなっています。世界に2億匹の犬がいるとしましょう。これはDogクラスのプロパティです。 Fidoは2億という数字とは関係がなく、Spotも関係ありません。上記のcolour
またはlegs
である「インスタンス属性」とは対照的に、「クラス属性」と呼ばれます。
今、より少ない犬とより多くのプログラミング関連のものに。以下に書いているように、物事を追加するクラスは賢明ではありません-それは何のクラスですか? Pythonのクラスは、異なるデータのコレクションで構成され、同様に動作します。犬のクラスは、FidoとSpot、およびそれらに類似した199999999998の他の動物で構成され、それらはすべて街灯でおしっこしています。物事を追加するためのクラスは何で構成されていますか?それらに固有のデータによって違いはありますか?そして、彼らはどんな行動を共有しますか?
しかし、数字...これらはより興味深いテーマです。言う、整数。それらの多くは、犬よりもはるかに多くあります。 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になると想定しています)が、今は無視します。実際のコードでは、そうしません。確認するためにテストし、おそらく強制することもあります(「あなたは整数ではありませんか?
分数を定義することもできます。分数も自分自身を追加する方法を知っています。
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
ここでは実際には何も宣言していません。属性は、新しい種類の変数のようなものです。通常の変数には1つの値しかありません。 colour = "grey"
と書いてみましょう。 colour
という名前の別の変数を"Fuchsia"
にすることはできません-コード内の同じ場所にはありません。
配列はそれをある程度解決します。 colour = ["grey", "Fuchsia"]
と言うと、変数に2色を重ねていますが、それらの位置(この場合は0または1)で区別します。
属性は、オブジェクトにバインドされる変数です。配列と同様に、多くのcolour
変数、異なる犬でを使用できます。したがって、fido.colour
は1つの変数ですが、spot.colour
は別の変数です。最初のものは変数fido
内のオブジェクトにバインドされます。 2番目のspot
。これで、Dog(4, "brown")
またはthree.add(five)
を呼び出すと、常に不可視のパラメーターが存在し、パラメーターリストの先頭にあるぶら下がり余分なパラメーターに割り当てられます。従来はself
と呼ばれ、ドットの前にあるオブジェクトの値を取得します。したがって、Dogの__init__
(コンストラクター)内では、self
は新しいDogになります。 MyInteger
のadd
内で、self
は変数three
のオブジェクトにバインドされます。したがって、three.value
は、add
内のself.value
と同じように、add
の外部と同じ変数になります。
the_mangy_one = fido
と言うと、fido
というオブジェクトを別の名前で参照し始めます。これ以降、fido.colour
はthe_mangy_one.colour
とまったく同じ変数です。
だから、__init__
の中のもの。それらは、犬の出生証明書に物事を記録していると考えることができます。 colour
自体はランダム変数であり、何でも含めることができます。 fido.colour
またはself.colour
は、犬のIDシートのフォームフィールドのようなものです。 __init__
は初めて記入する店員です。
より明確な?
EDIT:以下のコメントを展開:
objectsのリストを意味しますよね?
まず、fido
は実際にはオブジェクトではありません。これは変数であり、現在x = 5
と言っているように、x
は現在5番を含む変数です。後で気が変わったら、(クラスCat
を作成している限り)fido = Cat(4, "pleasing")
を実行でき、fido
はその後catオブジェクトを「含む」ことになります。 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__
のようなクラスバインド関数)の目的は、オブジェクトを印刷するときのように、オブジェクトを文字列に変換する方法を記述することです。
アマダンからの完全な説明 に私の5セントを寄付する。
ここで、クラスは抽象的な方法での「タイプの」記述です。オブジェクトは彼らの認識です:生きている呼吸物。オブジェクト指向の世界では、ほとんどすべてのものの本質と呼ぶことができる主要なアイデアがあります。彼らです:
オブジェクトには、1つ以上の特性(=属性)と動作(=メソッド)があります。動作は主に特性に依存します。クラスは、振る舞いが一般的な方法で何を達成すべきかを定義しますが、クラスがオブジェクトとして実現(インスタンス化)されない限り、可能性の抽象的な概念のままです。 「継承」と「ポリモーフィズム」の助けを借りて説明しましょう。
class Human:
gender
nationality
favorite_drink
core_characteristic
favorite_beverage
name
age
def love
def drink
def laugh
def do_your_special_thing
class Americans(Humans)
def drink(beverage):
if beverage != favorite_drink: print "You call that a drink?"
else: print "Great!"
class French(Humans)
def drink(beverage, cheese):
if beverage == favourite_drink and cheese == None: print "No cheese?"
Elif beverage != favourite_drink and cheese == None: print "Révolution!"
class Brazilian(Humans)
def do_your_special_thing
win_every_football_world_cup()
class Germans(Humans)
def drink(beverage):
if favorite_drink != beverage: print "I need more beer"
else: print "Lecker!"
class HighSchoolStudent(Americans):
def __init__(self, name, age):
self.name = name
self.age = age
jeff = HighSchoolStudent(name, age):
hans = Germans()
ronaldo = Brazilian()
amelie = French()
for friends in [jeff, hans, ronaldo]:
friends.laugh()
friends.drink("cola")
friends.do_your_special_thing()
print amelie.love(jeff)
>>> True
print ronaldo.love(hans)
>>> False
いくつかの特性は人間を定義します。しかし、国籍は多少異なります。ですから、「国民型」はちょっと余分な人間です。 「アメリカ人」は「人間」の一種であり、人間のタイプ(基本クラス)からいくつかの抽象的な特性と動作を継承します。それは継承です。それで、すべての人間は笑って飲むことができます、したがって、すべての子供クラスもそうすることができます!継承(2)。
しかし、それらはすべて同じ種類(Type/base-class:Humans)であるため、時々交換することができます:最後にforループを参照してください。しかし、それらは個々の特性を公開し、それが多態性(3)です。
そのため、各人はfavourite_drinkを持っていますが、すべての国籍は特別な種類の飲み物を好みます。ヒューマンのタイプから国籍をサブクラス化すると、drink()
メソッドを使用して上記で示したように、継承された動作を上書きできます。しかし、それはまだクラスレベルであり、このため、まだ一般化されています。
hans = German(favorite_drink = "Cola")
クラスGermanをインスタンス化し、最初にデフォルトの特性を「変更」しました。 (しかし、hans.drink( 'Milk')を呼び出すと、彼はまだ「もっとビールが必要」と表示します-明らかなバグ...または多分それが私がより大きな会社の従業員である場合、機能と呼ぶものです。 ;-)! )
タイプの特性(例:ドイツ語(hans)は通常、インスタンス化の瞬間にコンストラクター(python:__init__
)で定義されます。これが、オブジェクトになるクラスを定義するポイントです。個々の特性を満たし、オブジェクトになることで、抽象的な概念(クラス)に息吹を吹き込むことができます。
しかし、すべてのオブジェクトはクラスのインスタンスであるため、いくつかの基本的な特性タイプと動作をすべて共有しています。これは、オブジェクト指向の概念の大きな利点です。
各オブジェクトの特性を保護するには、それらをカプセル化します。つまり、動作と特性を組み合わせて、オブジェクトの外部から操作しにくくすることを意味します。それはカプセル化です(1)
インスタンスの変数を初期化するだけです。
例えば。特定のデータベース名でcrawler
インスタンスを作成します(上記の例から)。
インスタンスの可変属性を正しく初期化する場合は、Pythonで__init__
を使用する必要があるようです。
次の例を参照してください。
>>> class EvilTest(object):
... attr = []
...
>>> evil_test1 = EvilTest()
>>> evil_test2 = EvilTest()
>>> evil_test1.attr.append('strange')
>>>
>>> print "This is evil:", evil_test1.attr, evil_test2.attr
This is evil: ['strange'] ['strange']
>>>
>>>
>>> class GoodTest(object):
... def __init__(self):
... self.attr = []
...
>>> good_test1 = GoodTest()
>>> good_test2 = GoodTest()
>>> good_test1.attr.append('strange')
>>>
>>> print "This is good:", good_test1.attr, good_test2.attr
This is good: ['strange'] []
これは、各属性が新しい値で自動的に初期化されるJavaではまったく異なります。
import Java.util.ArrayList;
import Java.lang.String;
class SimpleTest
{
public ArrayList<String> attr = new ArrayList<String>();
}
class Main
{
public static void main(String [] args)
{
SimpleTest t1 = new SimpleTest();
SimpleTest t2 = new SimpleTest();
t1.attr.add("strange");
System.out.println(t1.attr + " " + t2.attr);
}
}
直感的に期待する出力を生成します:
[strange] []
ただし、attr
をstatic
として宣言すると、Pythonのように動作します。
[strange] [strange]
あなたのcarに従ってください:あなたが車を取得するとき、あなたはただランダムな車を取得しない、つまり、あなたは色、ブランドを選ぶ、座席の数など。また、ホイールの数や登録番号など、ユーザーが選択せずに「初期化」するものもあります。
class Car:
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.number_of_wheels = 4
self.registration_number = GenerateRegistrationNumber()
したがって、__init__
メソッドでは、作成するインスタンスの属性を定義します。したがって、2人用の青いルノー車が必要な場合は、次のようにCar
のインスタンスを初期化します。
my_car = Car('blue', 'Renault', 2)
このようにして、Car
クラスのインスタンスを作成しています。 __init__
は、特定の属性(color
やbrand
など)を処理し、registration_number
などの他の属性を生成するものです。
__init__
メソッド の詳細クラスは、そのオブジェクトに固有の属性(状態、特性)およびメソッド(機能、容量)を持つオブジェクトです(それぞれ、アヒルの白色および飛行力など)。
クラスのインスタンスを作成するときに、初期の性格(名前や新生児のドレスの色などの状態またはキャラクター)を与えることができます。これは__init__
で行います。
基本的に__init__
は、instance = MyClass(some_individual_traits)
を呼び出すときにインスタンスの特性を自動的に設定します。
__init__
関数は、クラス内のすべてのメンバー変数を設定しています。したがって、バイクラスターが作成されると、メンバーにアクセスして値を取得できます。
mycluster = bicluster(...actual values go here...)
mycluster.left # returns the value passed in as 'left'
Python Docs をご覧ください。学習を続けるには、OOの概念に関する本を選んでください。
class Dog(object):
# Class Object Attribute
species = 'mammal'
def __init__(self,breed,name):
self.breed = breed
self.name = name
上の例では、種は常に同じなので、種をグローバルとして使用します(定数の種類は言うことができます)。 __init__
メソッドを呼び出すと、__init__
内のすべての変数が開始されます(例:breed、name)。
class Dog(object):
a = '12'
def __init__(self,breed,name,a):
self.breed = breed
self.name = name
self.a= a
以下のように呼び出して上記の例を印刷すると
Dog.a
12
Dog('Lab','Sam','10')
Dog.a
10
つまり、オブジェクトの作成時にのみ初期化されます。そのため、定数として宣言するものはすべてグローバルとして変更し、変更するものはすべて__init__
を使用します