Pythonのようなオブジェクト指向プログラミング言語を使用する場合、Pythonにおけるカプセル化は、理解すべき4つの重要な概念のうちの1つです。
他の3つは、継承、ポリモーフィズム、抽象化です。
この記事もチェック:Pythonでオブジェクト指向の抽象化(ポリモーフィズム)について解説していく
カプセル化とは?
クラスや機密データを扱う場合、プログラム内で使用されるすべての変数にグローバルアクセスを提供することは良い選択ではありません。
カプセル化は、プログラムに本格的なアクセスを提供することなく、必要な変数にアクセスする方法を提供します。
変数のデータの更新、変更、削除は、その目的のために特別に定義されたメソッドを使用することで行うことができます。
このような方法でプログラミングを行うことで、入力データの制御性が向上し、セキュリティも強化されます。
この記事もチェック:Pythonでクラスのすべてのメソッドを一覧として表示する方法
Pythonにおけるカプセル化とは?
カプセル化の概念は、すべてのオブジェクト指向プログラミング言語で同じです。
違いは、その概念を特定の言語に適用したときに見られます。
Javaなどの言語が変数やメソッドにアクセス修飾子(publicやprivate)を与えるのに比べ、Pythonはすべての変数とメソッドにグローバルにアクセスできます。
以下のデモで、変数に簡単にアクセスできることを確認してください。
class Person:
def __init__( self , name, age = 0 ):
self .name = name
self .age = age
def display( self ):
print ( self .name)
print ( self .age)
person = Person( 'Dev' , 30 )
#accessing using class method person.display() #accessing directly from outside print (person.name)
print (person.age)
|
結果は以下の通りです。
Dev 30 Dev 30 |
Pythonにはアクセス修飾子がないので、Pythonのプログラム内で変数へのアクセスを制御するためにいくつかの異なる方法を使用します。
アクセス制御の方法
Pythonには、プログラム全体の変数やメソッドへのアクセスを制限するための複数のメソッドが用意されています。
それらのメソッドについて詳しく見ていきましょう。
シングルアンダーコアの使用
Pythonのプログラミングでは、プライベート変数を識別するためにアンダースコアを前に付けるのが一般的な慣習となっています。
さて、これはコンパイラ側では何の違いもありません。
この変数は通常通りアクセス可能です。
しかし、プログラマが知っている慣習なので、他のプログラマに、その変数やメソッドはそのクラスの範囲内だけで使わなければならないことを伝えることができます。
次の例を見てください。
class Person:
def __init__( self , name, age = 0 ):
self .name = name
self ._age = age
def display( self ):
print ( self .name)
print ( self ._age)
person = Person( 'Dev' , 30 )
#accessing using class method person.display() #accessing directly from outside print (person.name)
print (person._age)
|
結果は以下の通りです。
Dev 30 Dev 30 |
変数へのアクセスが変更されないことは明らかです。
しかし、本当に非公開にすることはできるのでしょうか?さらに見てみましょう。
ダブルアンダースコアの使用
クラスのメンバー、つまりメソッドや変数をプライベートにしたい場合は、プレフィクスとしてアンダースコアを2つ付けなければなりません。
しかし、Pythonはprivate修飾子に対してある種のサポートをしています。
この機構は Name mangling と呼ばれます。
これを使っても、クラスのメンバに外部からアクセスすることは可能です。
名前の揶揄
Pythonでは、Pythonインタープリターが、”index “に “gucci “を指定すると、”gucci “は現在のクラス名のまま、”gucci “はクラス名として書き換わります。
このように名前を変更する仕組みを Python では Name Mangling と呼びます。
以下の例では、クラス person の変数 age が変更され、先頭にダブルアンダースコアがついています。
class Person:
def __init__( self , name, age = 0 ):
self .name = name
self .__age = age
def display( self ):
print ( self .name)
print ( self .__age)
person = Person( 'Dev' , 30 )
#accessing using class method person.display() #accessing directly from outside print ( 'Trying to access variables from outside the class ' )
print (person.name)
print (person.__age)
|
結果は以下の通りです。
Dev 30 Trying to access variables from outside the class
Dev Traceback (most recent call last): File "Person.py" , line 16 , in <module>
print (person.__age)
AttributeError: 'Person' object has no attribute '__age'
|
この例では、変数へのアクセスはメソッドで行うことができます。
しかし、ageはプライベート変数なので、外から直接アクセスすることはできません。
ゲッターメソッドとセッターメソッドを使ってプライベート変数にアクセスする
プライベート変数にアクセスし、変更したい場合は、クラスの一部であるアクセッサ(ゲッター)メソッドとミューテータ(セッター)メソッドを使用する必要があります。
class Person:
def __init__( self , name, age = 0 ):
self .name = name
self .__age = age
def display( self ):
print ( self .name)
print ( self .__age)
def getAge( self ):
print ( self .__age)
def setAge( self , age):
self .__age = age
person = Person( 'Dev' , 30 )
#accessing using class method person.display() #changing age using setter person.setAge( 35 )
person.getAge() |
結果は以下の通りです。
Dev 30 35 |
Pythonにおけるカプセル化の利点
カプセル化はデータの流れを良くするだけでなく、外部からのデータを保護することもできます。
カプセル化のコンセプトはコードを自給自足にします。
実装レベルでは、「どのように」型の質問を優先し、複雑なことは置き去りにするので、非常に役に立ちます。
カプセル化を容易にするため、またデータの安全性を確保するために、データをユニット内に隠す必要があります。
Pythonでカプセル化の必要性は?
以下の理由は、開発者がカプセル化を便利だと思う理由と、オブジェクト指向のコンセプトが多くのプログラミング言語を凌駕している理由を示しています。
- カプセル化は、すべてのアプリケーションで明確に定義された相互作用を実現するのに役立ちます。
- オブジェクト指向のコンセプトは、Pythonのコードの再利用性に焦点を当てています。(DRY – Don’t Repeat Yourself).
- アプリケーションを安全に維持することができます。
- 適切なコード構成により、コードの柔軟性を確保します。
- バックエンドの複雑さを表に出すことなく、ユーザがスムーズに操作できるようになります。
- コードの可読性を向上させます。コードの一部分を変更しても、他の部分に支障をきたすことがありません。
- カプセル化は、データ保護を保証し、誤ってデータにアクセスすることを避けます。保護されたデータは、上で説明した方法でアクセスすることができます。
Pythonのカプセル化は、データがオブジェクトの定義の外側に隠されていることです。
これにより、開発者はユーザーフレンドリーなエクスペリエンスを開発することができます。
これは、コードが高度に保護され、外部からのアクセスが不可能であるため、違反からデータを保護するのにも役立ちます。
参考文献 Pythonのクラスとプライベート変数