新たな気づき(Chapter 12-3)
おっさんです。花粉症で集中できずにどうしてもこのクラスを扱う12章がもくもく会の会場で完結できなかったのを、意地で自宅で全てやりました。無理やりやっつけることが目的化し、完全に理解できているかは怪しいです。でもとにかく前に進みましょう。
- インスタンス変数にアンダースコアを2つ先頭につけるとクラスの外からのアクセス・参照ができなくなる。
class Person(): def __init__(self, name): self.__name = name #アンダースコア2つで外部参照不能になる def who(self): print(self.__name+"です。") #クラス内では利用可能 man=Person("宇佐美") man.who() #宇佐美です。 print(man.__name) #直接アクセスはエラー
- ただし、非公開にしたインスタンス変数も、ゲッター関数を用いて値を調べたり、セッター関数を用いて値を変更したり可能。ただ、1個の変数のアクセスに2個の関数を使うのは効率的とはいえないことから「プロパティ」の考え方を導入。デコレータ@propertyにつづいてゲッター関数を定義し、デコレータ@関数名.setterにつづいてセッター関数を定義する。この時ゲッターもセッターも関数名は共通にする。
@property def 関数名(self): return self.__非公開変数 #プロパティの値を取得し返す @関数名.setter def 関数名(self, value): self.__非公開変数 = value #プロパティに値を設定
- 以下の事例の場合、nameにはゲッターとセッターの両方を定義しているが、priceにはゲッターしか定義しておらずセッターがないので、shoes.priceで新たな値を設定しようとしてもエラーになる。
class Goods: #初期化メソッド def __init__(self, name, price): #非公開の__dataインスタンス変数(辞書) self.__data = {"name":name, "price":price} #nameプロパティ:ゲッター @property def name(self): return self.__data["name"] #nameプロパティ:セッター @name.setter def name(self, value): self.__data["name"] = value #priceプロパティ:ゲッター @property def price(self): price = self.__data["price"] price_str = f"{price:,}円" return price_str #priceプロパティのセッターは用意せず shoes = Goods("Dream",6800) print(shoes.name) #Dream shoes.name = "Dream Girls" print(shoes.name) #Dream Girls print(shoes.price) #6,800円 shoes.price = 7000 print(shors.price) #priceにはセッター関数がないのでエラー
- デコレータを使わずに、プロパティ変数 = property(ゲッター関数、セッター関数)で指定することもできる。具体的には以下のコードのようになるが、@で始まるデコレータが消えた代わりに、関数名にget_あるいはset_で始まるものになり、クラス定義の最後にproperty()を用いたプロパティの設定を行っている。アウトプットは上記の事例と同じ。
class Goods: #初期化メソッド def __init__(self, name, price): #非公開の__dataインスタンス変数(辞書) self.__data = {"name":name, "price":price} #nameプロパティ:ゲッター def get_name(self): return self.__data["name"] #nameプロパティ:セッター def set_name(self, value): self.__data["name"] = value #priceプロパティ:ゲッター def get_price(self): price = self.__data["price"] price_str = f"{price:,}円" return price_str #priceプロパティのセッターは用意せず #nameプロパティのゲッターとセッターを指定 name = property(get_name, set_name) #priceプロパティのゲッターを指定(セッターは指定せず) price = property(get_price) shoes = Goods("Dream",6800) print(shoes.name) #Dream shoes.name = "Dream Girls" print(shoes.name) #Dream Girls print(shoes.price) #6,800円 shoes.price = 7000 print(shors.price) #priceにはセッター関数がないのでエラー