Pythonのゲッターとセッター入門:カプセル化の基本から@propertyデコレータまで
オブジェクト指向プログラミングにおいて、データのカプセル化を実現するために、多くの言語ではゲッター(getter)とセッター(setter)と呼ばれるメソッドが使われます。その目的は、オブジェクトの属性を他のクラスから隠蔽し、外部のコードによってデータが誤って書き換えられることを防ぐことにあります。
名前が示すように、ゲッターはプライベート属性の値を取得(get)するためのメソッドであり、セッターはプライベート属性の値を設定・変更(set)するためのメソッドです。
属性へ直接アクセスしてみる
まずは、追加のメソッドを定義せずに、クラスを作成して初期化し、その変数へ直接アクセスするコードを見てみましょう。
サンプルコード
class YearGraduated:
def __init__(self, year=0):
self._year = year
# クラスをインスタンス化
grad_obj = YearGraduated()
# オブジェクト自体を表示
print(grad_obj)
# 属性の値を表示
print(grad_obj._year)実行結果
<__main__.YearGraduated object at 0x00F2DD50> 0
最初のprint文は生成されたオブジェクトの詳細情報を出力し、2つ目のprint文はデフォルト値で初期化された属性の値「0」を出力しています。このようにPythonでは、アンダースコア1つ(_year)を付けた属性であっても外部からアクセスできてしまう点に注意が必要です。
ゲッターとセッターを使う
次に、クラスを初期化した後、ゲッターメソッドとセッターメソッドをそれぞれ追加します。インスタンス化したオブジェクトに対してこれらのメソッドを通じて変数へアクセスすることで、処理ロジックをセッターメソッドの中に隠すことができます。
サンプルコード
class YearGraduated:
def __init__(self, year=0):
self._year = year
# ゲッターメソッド
def get_year(self):
return self._year
# セッターメソッド
def set_year(self, a):
self._year = a
grad_obj = YearGraduated()
# セッターを使用する前
print(grad_obj.get_year())
# セッターを使用した後
grad_obj.set_year(2019)
print(grad_obj.get_year())実行結果
0 2019
set_year()メソッドを呼び出すことで、内部の_year属性が2019に更新され、get_year()メソッド経由で新しい値を正しく取得できていることがわかります。
属性を完全にプライベートにする
続いて、変数を外部の関数から操作できないように、属性をプライベート化する方法を見ていきます。プライベートな属性はクラス内のメソッドからのみ操作可能で、属性名の先頭にアンダースコア2つ(__)を付けることで定義できます。
サンプルコード
class YearGraduated:
def __init__(self, year=32):
self.__year = year
# ゲッターメソッド
def get_year(self):
return self.__year
# セッターメソッド
def set_year(self, a):
self.__year = a
grad_obj = YearGraduated()
# ゲッター経由なら正常にアクセスできる
print(grad_obj.get_year())
grad_obj.set_year(2019)
print(grad_obj.get_year())
# 外部から直接アクセスするとエラーになる
print(grad_obj.__year)実行結果
32 2019 AttributeError: 'YearGraduated' object has no attribute '__year'
アンダースコア2つを付けた属性は、Pythonによって名前がマングリングされるため、クラスの外から直接参照しようとするとAttributeErrorが発生します。これにより、データへの不正なアクセスを防ぐことができます。
@propertyデコレータでスマートに読み書きする
Pythonでは、@propertyデコレータを使うことで、ゲッターやセッターを明示的に呼び出さなくても、あたかも通常の属性であるかのようにプライベートな値へアクセスできます。
サンプルコード
class YearGraduated:
def __init__(self, year=32):
self.__year = year
@property
def year(self):
return self.__year
@year.setter
def year(self, a):
self.__year = a
grad_obj = YearGraduated()
# 通常の属性のように値を取得
print(grad_obj.year)
# 通常の属性のように値を設定
grad_obj.year = 2018
print(grad_obj.year)実行結果
32 2018
@propertyを付けたメソッドはゲッターとして、@メソッド名.setterを付けたメソッドはセッターとして機能します。メソッド呼び出しの構文ではなく属性アクセスと同じシンプルな構文で読み書きできるため、よりPythonicで可読性の高いコードになります。
まとめ
Pythonでは、アンダースコア(_や__)を使った命名規則とゲッター・セッター、さらに@propertyデコレータを組み合わせることで、柔軟にカプセル化を実現できます。特別な処理が不要な場合は、@propertyを使うのが最もPythonらしい簡潔な書き方と言えるでしょう。
-
Python Kivy入門:ボタンアクション(イベント処理)の実装方法
Kivyは、マルチタッチアプリなど革新的なユーザーインターフェースを持つアプリケーションを迅速に開発するためのオープンソースのPythonライブラリです。Androidアプリだけでなく、デスクトップアプリケーションの開発にも広く活用されています。本記事では、Kivyにおいてボタンが押されたときにイベントを発生させる方法について解説します。実装例:ボタンとラベルの連動以下の例では、水平方向のBoxLayoutの中にボタンとラベルを1つずつ配置しています。まず、ボタンとラベルにそれぞれ初期テキストを設定します。その後、ボタンをクリックした際に発火するイベントを作成し、このイベントによってボタンとラ
-
Pythonの継承とは?単一継承と階層継承の基本をサンプルコードで解説
本記事では、Python 3.xにおける継承(インヘリタンス)とクラスの拡張方法について詳しく解説します。 継承とは、現実世界のモノや概念の関係性を自然に表現できる、オブジェクト指向プログラミングの中核となる仕組みです。継承を活用すると、次のようなメリットが得られます。 再利用性:すでに書いたコードを流用でき、重複を削減できる 推移性:クラス間の関係を連鎖的に引き継げる 開発速度の向上:ゼロから書かずに済むため、短期間で開発できる 保守性・拡張性:既存クラスを壊さずに機能を追加しやすい 継承の5つの種類 Pythonの継承は、その構造によって主に以下の5種類に分類されます。 単一継承(