おぼえがき

過ちては則ち改むるにうんぬんかんぬん

クラスをデータ構造体としてあつかう場合の注意点(Python)

f:id:feci:20210726231508j:plain

Python3

 

クラスをデータ構造体としてあつかう場合の注意点について。

#スーパークラス(親クラス)
class Ca(object):
  def __init__(selfa=None):  #親クラスのコンストラクター
    self.a = a                 #self.aにaを代入
  def fa(self):
    print('あいうえお')

#サブクラス(子クラス)
class Ca_a(Ca):          #引数に親クラスを指定することでクラスを継承
  def fa(self):          #オーバーライドで親のfaに上書きしてしまう
    print('かきくけこ')

#サブクラス(孫クラス)
class Ca_c(Ca_a):                         #Ca_aクラスのサブクラス
  def __init__(selfpasa='漢字'b=False):  #孫クラスのコンストラクター
    super().__init__(a)                   #親クラスのコンストラクターを呼び出して使用
    self.__b = b                          #bをself._bに代入・_を付けてbを隠し要素にする
    self.pas = pas

 #ゲッター
  @property        #デコレーターでpropertyを付与することでb関数はクラス変数として扱われる
  def b(self):     #この関数を呼び出すときはパレンティス(丸括弧)は必要ない
    return self.__b #bの値を返す

 #セッター
  @b.setter              #@propertyが付いている関数名に.setterをデコレートしてセッターにする
  def bs(selfc):       #この関数(セッター)もクラス変数と同じ記述で呼び出す
    if self.pas == 1234#コンストラクターのpasの値が1234のときだけbへの再代入を許可する
      self.__b = c       #bに引数cの値を再代入する
    else:
      raise ValueError   #pasの値が1234以外の場合はすべてValueErrorを返す

 def fa(self):    #オーバーライドで親(子)のfaに上書きしてしまう
    print('たちつてと')


#実行
cc = Ca_c(1234)  #孫クラスのインスタンスの作成・パラメータが1234以外の場合はセッターを呼び出すとError

cc.b = True   #Ca_cクラスのbの値を再代入したいが@property設定があるのでできない(AttribteError)
print(cc.b)   #False

cc.bs = True  #セッターを通しているのでbに再代入ができる
print(cc.b)   #True


#データ構造体として扱うパターン
print(cc.__b#__bはクラス外からアクセスできない(AttributeError)
cc.__b = True #Ca_cクラスに新しく__bプロパティを作ってしまう
print(cc.__b#値がFalseの__bにはアクセスできないが、上行のTrueの__bにはアクセスできてしまう

上記のスクリプトは、<セッターとゲッターについて>のページで解説に使ったスクリプトとほぼ同じです。

今回はこのスクリプトを使って、クラスをデータ構造体としてあつかう場合の注意点について説明していきます。

 

上記のスクリプトでは、Ca_aクラスのb引数の値を__bプロパティに代入してクラス外からアクセスできないように管理しています。

なので、クラス外からインスタンスを経由して print(cc.__b) と記述して実行しても、AttributeErrorが出るだけで__bプロパティの値は呼び出せません。

 

しかしクラス外からインスタンスを経由して cc.__b = True という形で新しい__bプロパティを作ってしまうと、その新しい__bプロパティには従来の形式の記述で問題なくアクセス(呼び出し&書き込み)ができてしまいます。

はっきりいって、これではデータのセキュリティもなにもあったものではありません。

 

このようにクラス外からそのクラスに新しいプロパティをどんどん作ってデータ構造体としてあつかう方法はデータの管理者側としては便利ではあるらしいのですが、重要なデータはやはりセッターやゲッターを使って管理するべきなのでしょう。

ご注意ください。

 

 

以上です。