①Pythonオブジェクト指向

スポンサーリンク

本当にわからないとこがあった場合一人では解決できません。
『teratail』とはエンジニア特化型のQ&Aサイトです。 すべてのエンジニアさんが抱えている悩みを共有して 解決するための質問サイトです
無料なのでまずは登録して使ってみてください。メールアドレスだけで登録可能です ----------------------------------------------------------------------------------------




Pythonオブジェクト指向

Pythonは誕生して以来、オブジェクト指向言語です。このため、クラスとオブジェクトの作成と使用は非常に簡単です。この章では、Pythonのオブジェクト指向プログラミングについて理解をしていきます。

オブジェクト指向(OO)プログラミングに関する以前の経験がない場合は、その入門コースまたは入門チュートリアルを参照して、基本的な概念を把握してください。

ここではまずオブジェクト指向プログラミング(OOP)を理解します


OOP用語の概要

  • クラス:任意のオブジェクトを特徴付ける一連の属性を定義するオブジェクトのユーザー定義プロトタイプ。例えば人間というクラスがあれば、人間の中には太郎や花子がいるくらいの感覚です
  • クラス変数:すべてのインスタンス間で共通した値をもつ変数です。クラス変数はインスタンスを生成することなく参照することができます。
  • データメンバー:クラスおよびそのオブジェクトに関連付けられたデータを保持するクラス変数またはインスタンス変数。つまり変数
  • 関数のオーバーロード:特定の関数に複数の動作を割り当てる。実行される操作は、関連するオブジェクトまたは引数のタイプによって異なります。
  • インスタンス変数:メソッド内で定義され、クラスの現在のインスタンスにのみ属する変数。
  • 継承:クラスの特性をそれから派生した他のクラスに移す。
  • インスタンス: 特定のクラスの個々のオブジェクト。例えばCircleクラスに属するオブジェクトobjは、Circleクラスのインスタンスです。
  • インスタンス化:クラスのインスタンスの作成。
  • メソッド:クラス定義で定義される特別な種類の関数。
  • オブジェクト:クラスによって定義されたデータ構造の一意のインスタンス。オブジェクトは、データメンバー(クラス変数とインスタンス変数)とメソッドの両方を含みます。
  • 演算子のオーバーロード:特定の演算子に複数の関数を割り当てる。

クラスの作成

クラスステートメントで、新しいクラス定義を作成します。

class ClassName:
   'Optional class documentation string'
   class_suite
  • クラスにはドキュメンテーション文字列があり、ClassName .__ doc__でアクセスできます。
  • class_suiteは、クラスメンバー、データ属性と機能を定義するすべてのコンポーネントの文で構成されています。

以下は、簡単なPythonクラスの例です。

class Employee:
   'Common base class for all employees'
   empCount = 0

   def __init__(self, name, salary): #ここで関数を宣言 defを使う
      self.name = name  #名前を拾ってくる
      self.salary = salary #給料を
      Employee.empCount += 1 #従業員のカウント
   
   def displayCount(self):#ここで関数を宣言 defを使う
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):#ここで関数を宣言 defを使う
      print "Name : ", self.name,  ", Salary: ", self.salary
  • 変数empCountは、このクラスのすべてのインスタンスで値が共有されるクラス変数です。これは、クラス内またはクラス外からEmployee.empCountとしてアクセスできます。
  • 最初のメソッド__init __()は特別なメソッドです。これは、このクラスの新しいインスタンスを作成するときにPythonが呼び出すクラスコンストラクタまたは初期化メソッドと呼ばれます。
  • 各メソッドの最初の引数がselfであることを除いて、通常の関数のような他のクラスメソッドを宣言します。Pythonはself引数をリストに追加します。メソッドを呼び出すときに含める必要はありません。

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

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

"最初のエンプロイクラス"
emp1 = Employee("Zara", 2000)
"次のエンプロイクラス"
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 #
%d 符号つき 10 進整
   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

"最初のエンプロイクラス"
emp1 = Employee("Zara", 2000)
"次のエンプロイクラス"
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  # Add an 'age' attribute.
emp1.age = 8  # Modify 'age' attribute.
del emp1.age  # Delete 'age' attribute.

属性にアクセスするために通常のステートメントを使用する代わりに、次の機能を使用できます。

  • GETATTR(OBJ、名[、デフォルト]) :オブジェクトの属性にアクセスします。
  • hasattr(OBJ、名):属性が存在するかどうかをチェックします。
  • SETATTR(OBJ、名前、値):属性を設定します。属性が存在しない場合は作成されます。
  • delattr(OBJ、名):属性を削除します。
hasattr(emp1, 'age')    # Returns true if 'age' attribute exists
getattr(emp1, 'age')    # Returns value of 'age' attribute
setattr(emp1, 'age', 8) # Set attribute 'age' at 8
delattr(empl, 'age')    # Delete attribute 'age'

組み込みクラス属性

すべてのPythonクラスは組み込みの属性を継承しており、他の属性と同様にドット演算子を使用してアクセスできます。

  • __dict__:クラスの名前空間を含む辞書。
  • __doc__:クラスのドキュメント文字列または未定義の場合はnone。
  • __name__:クラス名。
  • __module__:クラスが定義されているモジュール名。この属性は、対話モードでは “__main__”です。
  • __bases__:基底クラスを含む、おそらく空のタプル。基底クラスリストでの出現の順序。

上記のクラスでは、これらのすべての属性にアクセスしようとします。

#!/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':
<function displayCount at 0xb7c84994>, 'empCount': 2, 
'displayEmployee': <function displayEmployee at 0xb7c8441c>, 
'__doc__': 'Common base class for all employees', 
'__init__': <function __init__ at 0xb7c846bc>}

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

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

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

オブジェクトの参照カウントは、新しい名前が割り当てられたり、コンテナ(リスト、タプル、または辞書)に配置されると増加します。オブジェクトの参照カウントがdelで削除されたり、その参照が再割り当てされたり、その参照が有効範囲外になったりすると、オブジェクトの参照カウントは減少します。オブジェクトの参照カウントがゼロになると、Pythonはそれを自動的に収集します。

a = 40      # Create object <40>
b = a       # Increase ref. count  of <40> 
c = [b]     # Increase ref. count  of <40> 

del a       # Decrease ref. count  of <40>
b = 100     # Decrease ref. count  of <40> 
c[0] = -1   # Decrease ref. count  of <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) # prints the ids of the obejcts
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:        # define parent class
   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): # define child class
   def __init__(self):
      print "Calling child constructor"

   def childMethod(self):
      print 'Calling child method'

c = Child()          # instance of child
c.childMethod()      # child calls its method
c.parentMethod()     # calls parent's method
c.setAttr(200)       # again call parent's method
c.getAttr()          # again call parent's method

上記のコードを実行すると、次の結果が生成されます。

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

同様に、次のように複数の親クラスからクラスを駆動することができます。

class A:        # define your class A
.....

class B:         # define your class B
.....

class C(A, B):   # subclass of A and B
.....

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

  • issubclass(サブ、SUP)所与のサブクラス場合ブール関数は真を返すサブ実際スーパークラスのサブクラスであるSUP
  • でisinstance(OBJ、クラス)場合ブール関数は真を返すobjがクラスのインスタンスであり、クラスまたはクラスのサブクラスのインスタンスであります



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

親クラスのメソッドはいつでもオーバーライドできます。親のメソッドをオーバーライドする理由の1つは、サブクラスで特別な機能や異なる機能が必要な場合があるからです。

#!/usr/bin/python

class Parent:        # define parent class
   def myMethod(self):
      print 'Calling parent method'

class Child(Parent): # define child class
   def myMethod(self):
      print 'Calling child method'

c = Child()          # instance of child
c.myMethod()         # child calls overridden method

上記のコードを実行すると、次の結果が生成されます。

Calling child method

ベースオーバーロードのメソッド

次の表は、独自のクラスでオーバーライドできるいくつかの一般的な機能を示しています。

SN 方法、説明、サンプルコール
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 <module>
    print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'

Pythonはクラス名を含むように内部的に名前を変更することによってそれらのメンバーを保護します。object._className__attrNameなどの属性にアクセスできます。

.........................
print counter._JustCounter__secretCount

上記のコードを実行すると、次の結果が生成されます。

1
2
2



次のページ②

スポンサーリンク

プログラミングは独学からは挫折の可能性が高いです。まずは無料体験ができる
コードキャンプが本当におすすめ。無料体験でわからないところを聞きましょう。
転職補助つき。カリキュラム終了後に転職紹介をしてくれます。