はじめに
この実験では、Python のクラスとオブジェクトについて学びます。クラスはオブジェクトを作成するためのテンプレートです。オブジェクトはクラスのインスタンスです。
学習目標
- 名前とオブジェクト
- スコープと名前空間
- インスタンスオブジェクト
- メソッドオブジェクト
- 継承
- プライベート変数
この実験では、Python のクラスとオブジェクトについて学びます。クラスはオブジェクトを作成するためのテンプレートです。オブジェクトはクラスのインスタンスです。
Python でクラスを定義するには、class キーワードの後にクラス名を記述します。
クラス定義には __init__ メソッドを含める必要があります。これは、クラスからオブジェクトが作成されるときに呼び出される Python の特殊メソッドです。
新しい Python インタープリタを開きます。
python3
以下は、円を表すクラスの例です。
class Circle:
def __init__(self, radius):
self.radius = radius
__init__ メソッドは radius パラメータを受け取り、それをオブジェクトの radius 属性に割り当てます。
クラスからインスタンスオブジェクトを作成するには、クラス名の後に括弧を付けて呼び出します。これを「インスタンス」と呼ぶのは、クラスの具体的な実例であるからです。
circle1 = Circle(5)
これにより、半径が 5 の Circle 型のインスタンスオブジェクト circle1 が作成されます。インスタンスオブジェクトは、オブジェクトに固有のデータを格納するために使用できます。たとえば、各 Circle オブジェクトは異なる半径を持つことができます。
前のステップで定義した __init__ メソッドは、オブジェクトが作成されると自動的に呼び出され、オブジェクトの radius 属性は値 5 で初期化されます。
__init__ メソッドは、オブジェクトの初期状態を設定するためによく使用されます。たとえば、オブジェクトの属性を初期化したり、外部リソースへの接続を設定したりします。オブジェクトが作成されると自動的に呼び出されるため、自分で呼び出す必要はありません。
__init__ メソッドは通常のメソッドであり、任意の名前を付けることができることに注意してください。ただし、クラスの初期化メソッドであることを明確にするために、__init__ を使用することが推奨されています。
オブジェクトの属性にアクセスするには、ドット表記を使用します。たとえば、circle1 オブジェクトの半径にアクセスするには、次のコードを使用できます。
print(circle1.radius) ## Output: 5
属性に新しい値を割り当てることで、オブジェクトの属性を変更することができます。たとえば、circle1 オブジェクトの半径を変更するには、次のコードを使用できます。
circle1.radius = 10
print(circle1.radius) ## Output: 10
メソッドは、クラス内で定義された関数で、オブジェクトの属性に格納されたデータに対して操作を行うために使用されます。Python では、メソッドは def キーワードの後にメソッド名とパラメータのリストを記述して定義されます。
以下は、Circle クラス内で定義された area メソッドの例です。
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius * self.radius
area メソッドは、円の半径に基づいてその面積を計算します。これは、メソッドが呼び出されたオブジェクトの半径を参照する self.radius 属性を使用して行われます。
オブジェクトに対してメソッドを呼び出すには、ドット表記の後にメソッド名と括弧を付けます。たとえば、circle1 オブジェクトに対して area メソッドを呼び出すには、次のコードを使用できます。
circle1 = Circle(15)
print(circle1.area()) ## Output: 706.5
これにより、Circle クラスの特定のインスタンスである circle1 オブジェクトの面積が出力されます。
メソッドは、クラス内に機能をカプセル化し、オブジェクトの属性に格納されたデータを操作する方法を提供するのに役立ちます。
初心者は括弧の使い方に特に注意する必要があります。 括弧はオブジェクトに対してメソッドを呼び出すために使用され、またメソッドにパラメータを渡すためにも使用されます。これは最初は混乱するかもしれませんが、クラスとオブジェクトについて学習を続けるうちに明確になるでしょう。
インスタンスオブジェクトとメソッドオブジェクトは、Python の主な 2 種類のオブジェクトです。要するに、インスタンスオブジェクトはクラスから作成され、メソッドオブジェクトはクラス内で定義されます。
継承は、既存のクラスを修正した新しいクラスを作成する方法です。新しいクラスをサブクラス(サブクラス)と呼び、既存のクラスをスーパークラス(親クラス)と呼びます。
継承を使用すると、スーパークラスのすべての属性とメソッドを持つサブクラスを作成できます。また、サブクラスに追加の属性やメソッドを追加したり、スーパークラスの属性やメソッドをオーバーライドしたりすることもできます。
以下は、Circle クラスを継承したサブクラス Cylinder の例です。
class Cylinder(Circle):
def __init__(self, radius, height):
super().__init__(radius)
self.height = height
Cylinder クラスには、radius と height の 2 つのパラメータを受け取る __init__ メソッドがあります。このメソッドは、super() 関数を使用して Circle クラスの __init__ メソッドを呼び出し、オブジェクトの radius 属性を初期化し、その後オブジェクトの height 属性を設定します。
super() 関数は、Python の特殊な関数で、クラスのスーパークラスを参照します。サブクラス内からスーパークラスのメソッドを呼び出すために使用されます。
super() 関数はクラス定義内で定義され、作成されるオブジェクトを参照する self パラメータを受け取ります。呼び出されるメソッドに応じて、追加のパラメータを受け取ることもできます。この例では、radius パラメータを Circle クラスの __init__ メソッドに渡し、オブジェクトの radius 属性を初期化します。
Cylinder クラスは、Circle クラスのすべての属性とメソッドに加えて、追加の height 属性を持っています。Circle クラスと同じように、ドット表記を使用して Cylinder クラスの属性やメソッドにアクセスできます。
たとえば、Cylinder オブジェクトを作成し、その属性にアクセスするには、次のようにします。
cylinder1 = Cylinder(5, 10)
print(cylinder1.radius) ## 5 を出力
print(cylinder1.height) ## 10 を出力
継承は、オブジェクト指向プログラミングにおいてコードを再利用し、クラスの階層を作成するのに便利な機能です。
super() 関数は、サブクラスでスーパークラスのコードを再利用し、追加の機能で拡張したい場合に便利です。
super() 関数はスーパークラスへの静的な参照ではないことに注意する必要があります。これは、呼び出されるクラスに応じて変化する動的な参照です。これにより、複数レベルの継承で継承を使用し、各レベルで正しいスーパークラスにアクセスすることができます。
たとえば、次のクラスを考えてみましょう。
class A:
def method(self):
print("A method")
class B(A):
def method(self):
super().method()
print("B method")
class C(B):
def method(self):
super().method()
print("C method")
ここで、C は B のサブクラスで、B は A のサブクラスです。C オブジェクトで method メソッドを呼び出すと、まず super() 関数を使用して A クラスの method メソッドが呼び出され、次に super() 関数を使用して B クラスの method メソッドが呼び出され、最後に C クラスの method メソッドが呼び出されます。
obj = C()
obj.method() ## 「A method」、「B method」、「C method」を出力
super() 関数は、オブジェクト指向プログラミングにおいてコードを再利用し、クラスの階層を作成するのに便利な機能です。
Python では、プライベート変数は、定義されたクラス内でのみ使用されることを意図した変数であり、外部コードからは使用されないようになっています。プライベート変数は、クラスの外部から直接アクセスすることはできません。
Circle クラスでプライベート変数を定義するには、変数名の前に二重アンダースコア (__) を付けます。たとえば:
class Circle:
def __init__(self, radius):
self.__radius = radius
これにより、Circle クラス内にプライベート変数 __radius が定義されます。
プライベート変数は、定義されたクラス内でのみ使用されることを意図しています。クラスの外部から直接アクセスすることはできません。たとえば、Circle クラスの外部から __radius 変数にアクセスしようとすると、エラーが発生します:
circle1 = Circle(5)
print(circle1.__radius) ## これは AttributeError を引き起こします
プライベート変数は、クラス内にデータをカプセル化し、外部コードがそれを変更する能力を制限するのに役立ちます。ただし、Python ではプライベート変数は真にプライベートではなく、「名前修飾 (name mangling)」を使用してクラスの外部からアクセスすることができることに注意する必要があります。
名前修飾は、変数名に特別な接頭辞を付けて、クラスの外部からアクセスしにくくする手法です。
たとえば、__radius 変数は、次の構文を使用して Circle クラスの外部からアクセスすることができます:
print(circle1._Circle__radius) ## これは 5 を出力します
ただし、これは良いプログラミング慣行とは見なされず、避けるべきです。
代わりに、プライベート変数は定義されたクラス内でのみ使用し、必要に応じてデータにアクセスまたは変更するためのパブリックメソッドを提供する必要があります。
以下は、プライベートな __radius 変数と、半径にアクセスおよび変更するためのパブリックメソッドを持つ Circle クラスの例です:
class Circle:
def __init__(self, radius):
self.__radius = radius
def get_radius(self):
return self.__radius
def set_radius(self, radius):
self.__radius = radius
Circle オブジェクトの半径にアクセスするには、get_radius メソッドを使用できます:
circle1 = Circle(5)
print(circle1.get_radius()) ## 5 を出力
Circle オブジェクトの半径を変更するには、set_radius メソッドを使用できます:
circle1.set_radius(10)
print(circle1.get_radius()) ## 10 を出力
この実験では、Python のクラスとオブジェクトについて学びました。クラスを定義する方法、クラスからオブジェクトを作成する方法、オブジェクトの属性やメソッドにアクセスする方法、オブジェクトの属性を変更する方法、およびスーパークラスを継承したサブクラスを作成する方法を学びました。
この実験でカバーされた主要な概念の概要は次のとおりです。
__init__ メソッドは、クラスからオブジェクトが作成されるときに呼び出されます。これにより、オブジェクトの属性を設定することができます。この実験が Python のクラスとオブジェクトについての学習に役立ったことを願っています。何か質問があれば、教えてください!