Nicksの日記

spaCyに愛されたくて始めた日記

Pythonのプロパティ制御にgetterとsetter使うってよ

プロパティの定義 Pythonのようなオブジェクト指向プログラミング言語では、

オブジェクト(インスタンス)が持つデータそのもののこと

明確な定義が欲しいので調べてみたが、どれもだいたい同じような意味だったので

これで良い。

プロパティの制御 Pythonは外部からオブジェクトに簡単にアクセスできないようにしたかった。

そこでプロパティを完全に制御をかけようとした。当然、融通を効かせる必要が

ありますよね。「A変数は参照だけ。B変数は参照も変更も許可。」的な感じで。

その融通を効かせる担当にgetter(参照), setter(変更)を使います。

プラスアルファ、デコレータ(装飾)っていう「@」をうまいこと使うと

あら不思議、簡単でシンプルに制御をかけられるんですよ 

document: property

次の例でgetterやsetter(アクセサという)を実装しました。

self.__userはすぐあとで使うので記述しただけ。

コード内にある説明でコードの理解はできると思います

このコードで自分が理解できたこと
1. @propertyでprivate変数の参照ができる
2. 1.を定義したあとに@プロパティ名.setterで変数を書き換え可能にできる

class HomePage(object):

  def __init__(self, title, user):
    self.__title = title  
    self.__user = user


  @property # ①
  def title(self): 
    """
    titleはプロパティ名
    @propertyでgetterを意味する ①
    つまり、これで参照が可能 ②
    なのでこの段階で変更を加えようとすると ③
    なのでtitleはこの段階では参照しかできない
    オブジェクトになります
    """


    return self.__title


  @title.setter # ④
  def title(self, new_title): # ⑤
    """
    titleプロパティのsetterを定義した ④
    これでprivate変数を変更することが可能です
    new_titleが新しいタイトル ⑤
    setterを定義したので,③のエラーがなくなります ⑥
    """
    self.__title = new_title


  
H = HomePage("Nicks days", "nicks")
print(H.title)      # ②
#H.title = "Holmes" # ③ AttributeError: can't set attribute


H.title = "Holmes"  # ⑥ エラーは出ません
print(H.title)      # タイトルがHolmesに変わってると思います  

 

次はさっき言ってたuserについて。

これを参照だけにしてみます。

class HomePage(object):

  def __init__(self, title, user):
    self.__title = title  
    self.__user = user

  @property
  def title(self): 
    return self.__title

  @title.setter
  def title(self, new_title):
    self.__title = new_title

  
  # userは参照だけ ①
  @property # getterを意味する.
  def user(self):
    return self.__user


H = HomePage("Nicks days", "nicks")
print(H.user) # ① 参照は可能
H.user = "Holmes" # これはエラーが返ってくる

 ここまでは割と自分でも問題ありませんでした。

次に自分が思ったのはもっとかっこよっく書けないかなって思ったんですよね。

getterを書かずにsetterを定義して、getter, setterを使わない方法を

方法が3つほどありました。

  1. デコレータを外せばいい。つまり、property()の引数fsetにgetterする関数を渡す
  2. __setattr__()を使う
  3. .__set__()のみを実行するディスクリプタを作る
    長くなったので次回はこの続きから書いていきます

Twitterフォローよろしくおねがいします。