Python 3 オブジェクト指向

Pythonはオブジェクト指向言語であり、だからこそ、Pythonでクラスとオブジェクトを簡単に作成できます。この記事では、Pythonのオブジェクト指向プログラミングについて詳しく紹介します。

これまでオブジェクト指向のプログラミング言語に触れたことがなければ、オブジェクト指向言語の基本的な機能のいくつかを理解し、基本的なオブジェクト指向の概念を理解する必要があります。これは、Pythonオブジェクト指向のプログラミングの学習に役立ちます。

次には、オブジェクト指向の基本的な特徴を簡単に理解しましょう。

オブジェクト指向の説明

  • クラス(Class):同じプロパティとメソッドを持つオブジェクトの集合を説明するために使用されます。集合内の各オブジェクトに共通の属性とメソッドを定義します。オブジェクトはクラスのインスタンスです。
  • メソッド:クラスで定義された関数。
  • クラス変数:クラス変数は、インスタンス化されたオブジェクト全体で共通です。クラス変数は、クラス内および関数本体の外部で定義されます。クラス変数は通常、インスタンス変数として使用されません。
  • データメンバー:クラス変数またはインスタンス変数は、クラスとそのインスタンスオブジェクトに関連するデータを処理するために使用されます。
  • メソッドを書き換える:親クラスから継承されたメソッドが子クラス(サブクラス)のニーズを満たせない場合は、書き換えることができます。このプロセスは、メソッドのオーバーライド(override)と呼ばれ、メソッドの書き換えとも呼ばれます。
  • ローカル変数:メソッドで定義された変数は、現在のインスタンスのクラスにのみ作用します。
  • インスタンス変数:クラスの宣言では、属性は変数で表されます。このような変数はインスタンス変数と呼ばれ、インスタンス変数はselfで修飾された変数です。
  • 継承:つまり、派生クラス(derived class)は基本クラス(base class)のフィールドとメソッドを継承します。継承により、派生クラスのオブジェクトを基本クラスオブジェクトとします。次には、DogタイプはAnimalクラスから派生し、「is-a」関係をシミュレートするデザインの例を挙げます。(DogはAnimalです)。
  • インスタンス化:クラスのインスタンスを作成し、具体的なオブジェクトです。
  • オブジェクト:クラスによって定義されたデータ構造のインスタンス。オブジェクトには、2つのデータメンバー(クラス変数とインスタンス変数)とメソッドが含まれます。

他のプログラミング言語と比較して、Pythonは、新しいステートメントをできるだけ追加せずに、クラスメカニズムを追加します。

Pythonのクラスは、オブジェクト指向プログラミングのすべての基本機能を提供します。クラスの継承メカニズムにより、複数の基本クラスが可能になり、派生クラスは基本クラスの任意のメソッドをカバーでき、基本クラスの同じ名前のメソッドをで呼び出すことができます。

オブジェクトには、任意の数量とタイプのデータを含めることができます。

クラスの定義

構文は次のとおりです。

class ClassName: 
<statement-1> 
. 
. 
.
 <statement-N>

クラスがインスタンス化された後、そのプロパティを使用できます。実際、クラスが作成された後、クラス名によって、プロパティにアクセスできます。

クラスのオブジェクト

クラスのオブジェクトは属性の参照とインスタンス化の2つの操作をサポートします。

属性の参照は、Pythonのすべての属性の参照と同じ標準構文obj.nameを使用します。

クラスのオブジェクトが作成された後、クラス名内のすべての名前は有効な属性名になります。クラスの定義が次のような場合:

実例(Python 3.0+)

#!/usr/bin/python3
 
class MyClass:
    """簡単的なクラスのインスタンス"""
    i = 12345
    def f(self):
        return 'hello world'
 
# インスタンス化されたクラス
x = MyClass()
 
# クラスの属性とメソッドにアクセスする
print("MyClass クラスの属性iは:", x.i)
print("MyClass クラスのメソッドfの出力は:", x.f())以上は新しいクラスのインスタンスを作成し、そのオブジェクトをローカル変数xに割り当て、xは空のオブジェクトです。

上記のプログラムを実行した結果は次のとおりです。

MyClassクラスの属性iは:12345
MyClassクラスのメソッドfの出力は:hello world

クラスには、init()と呼ばれる特別なメソッド(構築メソッド)があります。これは、次のように、クラスがインスタンス化されるときに自動的に呼び出されます。

def __init__(self):
self.data = []

クラスは __init__() メソッドを定義し、クラスのインスタンス化操作は自動的に__init__()メソッドを呼び出します。例えば、クラスMyClassをインスタンス化すると、対応する__init__()メソッドが呼び出されます。

x = MyClass()

勿論、__init__()メソッドはパラメータを持つことができ、パラメータは__init__()を介してクラスのインスタンス化操作に渡されます。例えば:

実例(Python 3.0+)

#!/usr/bin/python3
 
class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i)   # 出力結果:3.0 -4.5

selfはクラスでなく、クラスのインスタンスを代表します

クラスメソッドと通常の関数との違いはただ1つです。つまり、最初のパラメータ名を追加する必要があります。これは、慣例により、selfという名前です。

class Test:
    def prt(self):
        print(self)
        print(self.__class__)
t = Test()

t.prt()上記の例の実行結果は次のとおりです。

<__main__.Test instance at 0x100771878>
__main__.Test

実行結果から見ると、selfはクラスのインスタンスを代表し、現在のオブジェクトのアドレスを表し、self.classはクラスを指していることが分かります。

selfはpythonキーワードではないため、runoobに置き換えることができ、正常に実行できます。

class Test:
    def prt(runoob):
        print(runoob)
        print(runoob.__class__)
 
t = Test()
t.prt()

上記の例の実行結果は次のとおりです。

<__main__.Test instance at 0x100771878>
__main__.Test

クラスメソッド

クラス内では、defキーワードを使用してメソッドを定義します。一般的な関数の定義と異なり、クラスメソッドにはselfを含める必要である以外、selfも最初のパラメータにする必要があります。Selfはクラスのインスタンスを代表します。

実例(Python 3.0+)

#!/usr/bin/python3
 
#クラスの定義
class people:
    #基本属性を定義する
    name = ''
    age = 0
    #プライベートな属性を定義し、プライベートな属性はクラスの外から直接アクセスできない。
    __weight = 0
    #構造メソッドを定義する
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s : 私は %d 才です。" %(self.name,self.age))

# クラスをインスタンス化する
p = people('Florian',10,30)
p.speak()

上記のプログラムを実行した結果は次のとおりです。

Florian : 私は 10 才です。

継承

Pythonはクラスの継承もサポートしています。言語が継承をサポートしていない場合、クラスには意味がありません。派生クラスの定義は次のとおりです。

class DerivedClassName(BaseClassName):
    <statement-1>
    .
    .
    .
<statement-N>

サブ(子)クラス(派生クラスDerivedClassName)は、親クラス(基本クラスBaseClassName)の属性とメソッドを継承します。

BaseClassName(インスタンスの基本クラス名)は、派生クラスのスコープで定義する必要があります。クラス以外、数式を使用できます。これは、基本クラスが別のモジュールで定義されている場合に非常に役立ちます。

class DerivedClassName(modname.BaseClassName):

実例(Python 3.0+)

#!/usr/bin/python3
 
#クラスの定義
class people:
    #基本属性を定義する
    name = ''
    age = 0
    #プライベートな属性を定義し、プライベートな属性はクラスの外から直接アクセスできない。
    __weight = 0
    #構造メソッドを定義する
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s : 私は %d 才です。" %(self.name,self.age))

#単一継承の例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #親クラスのコンストラクターを呼び出す
        people.__init__(self,n,a,w)
        self.grade = g
    #親クラスのメソッドをオーバーライドする
    def speak(self):
        print("%s : 私は %d 才で、 %d 年生です"%(self.name,self.age,self.grade))

s = student('ken',10,60,3)
s.speak()

上記のプログラムを実行した結果は次のとおりです。

ken:私は10才で、3年生です

多重継承

Pythonは、多重継承をある程度でサポートします。 多重継承のクラス定義は次のとおりです。

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

括弧内の親クラスの順序に注意する必要があります。親クラスが同じメソッド名であるが、サブクラスが使用されるときに指定されていない場合、Pythonは左から右に検索します。つまり、メソッドがサブクラスで見つけない場合、親クラスに左から右メソッドが含まれているかどうかを検索します。

実例(Python 3.0+)

#!/usr/bin/python3
 
#クラスの定義
class people:
    #基本属性を定義する
    name = ''
    age = 0
    #プライベートな属性を定義し、プライベートな属性はクラスの外から直接アクセスできない。
    __weight = 0
    #構造メソッドを定義する
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s : 私は %d 才です。" %(self.name,self.age))

#単一継承の例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #親クラスのコンストラクターを呼び出す
        people.__init__(self,n,a,w)
        self.grade = g
    #親クラスのメソッドをオーバーライドする
    def speak(self):
        print("%s : 私は %d 才で、 %d 年生です"%(self.name,self.age,self.grade))

#別のクラス、多重継承前の準備
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("私は %sと申します。私は演説者であり、発表するテーマは %sです"%(self.name,self.topic))

#多重継承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
 
test = sample("Tim",25,80,4,"Python")
test.speak()   #メソッド名は同じである場合、デフォルトでは、括弧内、最初の親クラスのメソッドを呼び出す

上記のプログラムを実行した結果は次のとおりです。

私はTimと申します。私は演説者であり、発表するテーマは Pythonです

メソッドの書き換え

親クラスのメソッドの関数が需要を満たせない場合は、サブクラスの親クラスのメソッドをオーバーライドできます。例は次のとおりです。

実例(Python 3.0+)

#!/usr/bin/python3
 
class Parent:        # 親クラスを定義する
   def myMethod(self):
      print ('親メソッドを呼び出す')
 
class Child(Parent): # サブ(子)クラスを定義する
   def myMethod(self):
      print ('子メソッドを呼び出す')
 
c = Child()          # サブ(子)クラスインスタンス
c.myMethod()         # サブ(子)クラスは書き換えるメソッドを呼び出す
super(Child,c).myMethod() #サブ(子)クラスオブジェクトによって、オーバーライドされた親クラスのメソッドを呼び出す

super()関数は、親クラス(スーパークラス)を呼び出すために使用されるメソッドです。

上記のプログラムを実行した結果は次のとおりです。

子メソッドを呼び出す
親メソッドを呼び出す

クラスの属性とメソッド

クラスの private属性

__private_attrs:2つのアンダースコアで始まり、属性がprivateであり、クラスの外部で使用または直接アクセスできないことを宣言します。クラス内部のメソッドで使用する場合:self.__private_attrs。

クラスメソッド

クラス内では、defキーワードを使用してメソッドを定義します。通常の関数定義とは異なり、クラスメソッドには、selfは最初のパラメータである必要があります。Selfはクラスのインスタンスを代表します。

selfの名前はオプションで、thisも使用できますが、慣習でselfを使用することをお勧めします。

クラスのprivateメソッド

__private_method:2つのアンダースコアで始まり、メソッドがprivateメソッドであり、クラスの外部ではなく、クラスの内部でのみ呼び出すことができることを宣言します。 self.__private_methods。

実例

クラスのprivate属性の実例は次のとおりです。

実例(Python 3.0+)
#!/usr/bin/python3
 
class JustCounter:
    __secretCount = 0  # secret変数
    publicCount = 0    # public変数

  def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print (self.__secretCount)
 
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount)  # エラーが発生します。実例は secret変数にアクセスできません

上記のプログラムの出力結果は次のとおりです。

1
2
2
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    print (counter.__secretCount)  # エラーが発生します。実例は secret変数にアクセスできません
AttributeError: 'JustCounter' object has no attribute '__secretCount'

クラスのprivateメソッドの実例は次のとおりです。

実例(Python 3.0+)

#!/usr/bin/python3
 
class Site:
    def __init__(self, name, url):
        self.name = name       # public
        self.__url = url   # private
 
    def who(self):
        print('name  : ', self.name)
        print('url : ', self.__url)

def __foo(self):          # privateメソッド
        print('これはprivateメソッドです')
 
    def foo(self):            # publicメソッド
        print('これはpublicメソッドです')
        self.__foo()

x = Site('初心者チュートリアル', 'www.ceodata.com')
x.who()        # 通常の出力
x.foo()        # 通常の出力
x.__foo()      # エラーが発生します

上記の実例の実行結果:

クラス固有のメソッド

__init__ : 構造関数、オブジェクトを生する時に呼び出す
__del__ : デストラクタ関数、オブジェクトを解放する時に使用する
__repr__ : 印刷、変換
__setitem__ : インデックスに従って値を割り当てる
__getitem__: インデックスに従って値を取得する
__len__: 長さを取得する
__cmp__: 比較
__call__: 関数を呼び出す
__add__: 加算
__sub__: 減算
__mul__: 乗算
__truediv__: 除算
__mod__: 余り計算
__pow__: 冪乗

演算子のオーバーロード

Pythonは、演算子のオーバーロードもサポートします。クラスの固有のメソッドをオーバーロードできます。実例は次のとおりです。

実例(Python 3.0+)

#!/usr/bin/python3
 
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)
Share

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です