工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Python

Pythonオブジェクト指向プログラミング完全ガイド:クラスと継承をマスター

OOP用語の概要

クラスの作成

class文は新しいクラス定義を作成します。クラス名はキーワードclassの直後に続き、コロンで終わります。

class ClassName:
    'Optional class documentation string'
    class_suite

例

シンプルなPythonクラスの例:

class Employee:
    'Common base class for all employees'
    empCount = 0
    
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
    
    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)
    
    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)

インスタンスオブジェクトの作成

クラスのインスタンスを作成するには、クラス名を使用してクラスを呼び出し、その__init__メソッドが受け入れる引数を渡します。

"Employeeクラスの最初のオブジェクトを作成"
emp1 = Employee("Zara", 2000)
"Employeeクラスの2番目のオブジェクトを作成"
emp2 = Employee("Manni", 5000)

属性へのアクセス

オブジェクトの属性には、オブジェクトと共にドット演算子を使用してアクセスします。クラス変数はクラス名を使用してアクセスします。

emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)

すべての概念を組み合わせた完全な例:

#!/usr/bin/python
class Employee:
    'Common base class for all employees'
    empCount = 0
    
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
    
    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)
    
    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)

emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)

実行結果:

Name : Zara ,Salary: 2000
Name : Manni ,Salary: 5000
Total Employee 2

クラスとオブジェクトの属性は、いつでも追加、削除、変更できます。

emp1.age = 7  # 'age'属性を追加
emp1.age = 8  # 'age'属性を変更
del emp1.age  # 'age'属性を削除

通常の文で属性にアクセスする代わりに、以下の関数を使用することもできます。

hasattr(emp1, 'age')  # 'age'属性が存在すればTrueを返す
getattr(emp1, 'age')  # 'age'属性の値を返す
setattr(emp1, 'age', 8)  # 'age'属性を8に設定
delattr(emp1, 'age')  # 'age'属性を削除

組み込みクラス属性

すべてのPythonクラスは以下の組み込み属性を保持し、他の属性と同様にドット演算子でアクセスできます。

上記クラスでこれらすべての属性にアクセスしてみます:

#!/usr/bin/python
class Employee:
    'Common base class for all employees'
    empCount = 0
    
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
    
    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)
    
    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)

print("Employee.__doc__:", Employee.__doc__)
print("Employee.__name__:", Employee.__name__)
print("Employee.__module__:", Employee.__module__)
print("Employee.__bases__:", Employee.__bases__)
print("Employee.__dict__:", Employee.__dict__)

実行結果:

Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': , 'empCount': 2, 'displayEmployee': , '__doc__': 'Common base class for all employees', '__init__': }

オブジェクトの破棄(ガベージコレクション)

Pythonは、不要になったオブジェクト(組み込み型またはクラスインスタンス)を自動的に削除してメモリ空間を解放します。Pythonが使用されなくなったメモリブロックを定期的に回収するプロセスをガベージコレクションと呼びます。

Pythonのガベージコレクタはプログラム実行中に動作し、オブジェクトの参照カウントがゼロになるとトリガーされます。オブジェクトの参照カウントは、それを指すエイリアスの数が変わると変化します。

a = 40      # オブジェクト <40> を作成
b = a       # <40> の参照カウント増加
c = [b]     # <40> の参照カウント増加
del a       # <40> の参照カウント減少
b = 100     # <40> の参照カウント減少
c[0] = -1   # <40> の参照カウント減少

ガベージコレクタが孤立したインスタンスを破棄してそのスペースを回収する瞬間を通常は意識しません。しかし、クラスは特殊メソッド__del__()(デストラクタと呼ばれる)を実装でき、インスタンスが破棄される直前に呼び出されます。このメソッドは、インスタンスが使用していた非メモリリソースのクリーンアップに使用できます。

例

この__del__()デストラクタは、破棄されるインスタンスのクラス名を出力します。

#!/usr/bin/python
class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
    
    def __del__(self):
        class_name = self.__class__.__name__
        print(class_name, "destroyed")

pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3))  # オブジェクトのIDを表示
del pt1
del pt2
del pt3

実行結果:

3083401324 3083401324 3083401324
Point destroyed

注 - 理想的には、クラスを別ファイルに定義し、メインプログラムファイルでimport文を使用してインポートすべきです。

クラスの継承

ゼロから始める代わりに、既存のクラスから派生させてクラスを作成できます。新しいクラス名の後に括弧で親クラスを列挙します。

子クラスは親クラスの属性を継承し、それらをあたかも子クラスで定義されたかのように使用できます。子クラスは親からデータメンバとメソッドをオーバーライドすることもできます。

構文

派生クラスは親クラスとよく似ていますが、クラス名の後に継承する基底クラスのリストが続きます。

class SubClassName (ParentClass1[, ParentClass2, ...]):
    'Optional class documentation string'
    class_suite

例

#!/usr/bin/python
class Parent:
    # 親クラスを定義
    parentAttr = 100
    
    def __init__(self):
        print("Calling parent constructor")
    
    def parentMethod(self):
        print('Calling parent method')
    
    def setAttr(self, attr):
        Parent.parentAttr = attr
    
    def getAttr(self):
        print("Parent attribute :", Parent.parentAttr)

class Child(Parent):
    # 子クラスを定義
    def __init__(self):
        print("Calling child constructor")
    
    def childMethod(self):
        print('Calling child method')

c = Child()          # 子クラスのインスタンス
c.childMethod()      # 子クラスのメソッドを呼び出し
c.parentMethod()     # 親クラスのメソッドを呼び出し
c.setAttr(200)       # 再び親クラスのメソッドを呼び出し
c.getAttr()          # 再び親クラスのメソッドを呼び出し

実行結果:

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

同様に、複数の親クラスからクラスを派生させることもできます。

class A:
    # クラスAを定義
    .....
class B:
    # クラスBを定義
    .....
class C(A, B):
    # AとBのサブクラス
    .....

issubclass()やisinstance()関数を使用して、2つのクラスとインスタンスの関係をチェックできます。

メソッドのオーバーライド

親クラスのメソッドをいつでもオーバーライドできます。オーバーライドする理由の一つは、サブクラスで特別なまたは異なる機能を望む場合です。

例

#!/usr/bin/python
class Parent:
    # 親クラスを定義
    def myMethod(self):
        print('Calling parent method')

class Child(Parent):
    # 子クラスを定義
    def myMethod(self):
        print('Calling child method')

c = Child()          # 子クラスのインスタンス
c.myMethod()         # 子クラスがオーバーライドしたメソッドを呼び出し

実行結果:

Calling child method

基本オーバーロードメソッド

以下の表は、独自のクラスでオーバーライドできる汎用機能の一部を示しています。

No.メソッド、説明、サンプル呼び出し
1__init__ ( self [,args...] ) - コンストラクタ(オプション引数付き)
サンプル呼び出し: obj = className(args)
2__del__( self ) - デストラクタ、オブジェクトを削除
サンプル呼び出し: del obj
3__repr__( self ) - 評価可能な文字列表現
サンプル呼び出し: repr(obj)
4__str__( self ) - 表示可能な文字列表現
サンプル呼び出し: str(obj)
5__cmp__ ( self, x ) - オブジェクト比較
サンプル呼び出し: cmp(obj, x)

演算子のオーバーロード

2次元ベクトルを表すVectorクラスを作成したとします。それらをプラス演算子で加算しようとすると、Pythonはエラーを出すでしょう。

しかし、クラスに__add__メソッドを定義してベクトル加算を実行するようにすれば、プラス演算子が期待通りに動作します。

例

#!/usr/bin/python
class Vector:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    
    def __str__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)
    
    def __add__(self, other):
        return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)

実行結果:

Vector(7,8)

データ隠蔽

オブジェクトの属性は、クラス定義の外部からは見えない場合があります。属性名をダブルアンダースコアで始めると、それらの属性は外部から直接見えなくなります。

例

#!/usr/bin/python
class JustCounter:
    __secretCount = 0
    
    def count(self):
        self.__secretCount += 1
        print(self.__secretCount)

counter = JustCounter()
counter.count()
counter.count()
print(counter.__secretCount)

実行結果:

1
2
Traceback (most recent call last):
  File "test.py", line 12, in 
    print(counter.__secretCount)
AttributeError: JustCounter instance has no attribute '__secretCount'

Pythonはこれらのメンバを、クラス名を含むように内部的に名前を変更することで保護します。このような属性にはobject._className__attrNameとしてアクセスできます。最後の行を以下のように置き換えると動作します。

print(counter._JustCounter__secretCount)

実行結果:

1
2
2

Python

  1. Raspberry PiとOpenCVによる自動ビジョンベース物体追跡
  2. C# クラスとオブジェクト:堅牢な OOP の基礎
  3. Python データ型マスター: 実践ガイド
  4. Python 演算子完全マスター: 包括的ガイド
  5. Python pass文完全マスター: 実践ガイド
  6. Python辞書完全ガイド:作成、操作、高度なテクニック
  7. Pythonカスタム例外マスター:実践ガイド
  8. Pythonオブジェクト指向プログラミング完全ガイド:クラス、継承、カプセル化、ポリモーフィズム
  9. Python継承マスター:概念、構文、実践例
  10. Python type()とisinstance()の理解:実例付き解説
  11. Javaシングルトンパターン完全解説:安全な実装と活用法