Python学習【365日チャレンジ!】81日目のマスターU(@Udemy11)です。
体重が増えてきたので、意識してウォーキングをしているのですが、田舎はやっぱり星空がきれいなんですよね。
あたりまえにこんな星空があるので、その美しさになかなか気づくことができません。
今いる世界とは違った世界に行くことで、違う世界のことがわかり、そして自分が今までいた世界の素晴らしさに気づくことができます。
心地よいコンフォートゾーンから飛び出して、アウトオブコンフォートゾーンへ踏み出してみてください。
これまで見ていた世界が違ったものに見えるようになるはずです。
それではPython学習をすすめましょう。
昨日の復習
昨日は、メソッドのオーバーライドと親メソッドのsuperについて学習しました。
ベースクラスで定義されたメソッドの値などを上書きするのがオーバーライドで、super()
を使うことでベースクラスの一部の引数だけを変更することもできました。
class Car:
def __init__(self, name=None):
self.model = name
class ToyotaCar(Car):
def __init__(self, name='Crown', auto_drive=False):
super().__init__(name)
self.drive = auto_drive
toyota_car = ToyotaCar()
print('Name:', toyota_car.model)
print('Auto Drive:', toyota_car.drive)
出力結果
Name: Crown
Auto Drive: False
内容がかなり複雑になっているので、理解するのにかなり時間がかかってしまいますが、ここできちんと理解しておかないと、この先はどんどんわからなくなってしまいます。
super()
については、時間をかけて理解したほうがいいので、昨日の記事でしっかりと復習しておきましょう!
それでは本日の学習に入ります。
@propertyの使い方
憶えていますか?
@
をつけて処理を行うデコレーター。
@property
は、組み込み関数property
をデコレーターにしたものです。
組み込み関数であるproperty
をデコレーターとして活用することで、読み込み専用の属性を持った引数を定義することができます。
class Car:
def __init__(self,name='NXS', auto_drive=False):
self.model = name
self._drive = auto_drive
@property
def drive(self):
return self._drive
car = Car()
print(car.model)
print(car.drive)
出力結果
NXS
False
4行目のself._drive
を6-8行目で新しくdrive
メソッドとして@property
でデコレートすることで、最終的な引数となるauto_drive
が書き換えられないようにしています。
ちょっとわかりづらいとおもいますが、Car
クラスから作られたcar
インスタンスには、car.model
、car._drive
、car.drive
の3つのクラス変数が定義されていて、@property
でデコレートされたcar.drive
だけが読み込み専用のクラス変数になります。
car.drive
には、6-8行目でcar._drive
、つまり変数auto_drive
が渡されるので、auto_drive
を変更することはできないということです。
setterで変更可能にする
@property
でクラス変数を読み込み専用にすることができるわけですが、変更可能にすることもできます。
class Car:
def __init__(self,name='NXS', auto_drive=False):
self.model = name
self._drive = auto_drive
@property
def drive(self):
return self._drive
@drive.setter
def drive(self, is_enable):
self._drive = is_enable
car = Car()
print(car.model)
car.drive = True
print(car.drive)
出力結果
NXS
True
@property
で読み込み専用にしたクラス変数のdrive
を10行目で.setter
をつけたデコレーターにして、11-12行目で新しい引数を与えてオーバーライドすることで、クラス変数のdrive
を変更可能にしています。
条件をつけて書き換え可能に
単純にここまでのことだけを学習していると、
こんな面倒なこと必要?
なんて考えが浮かんできます。
わざわざ読み込み専用にして、それを書き換えられるようにする必要ある?と思っちゃいませんか?
そこは、ちゃんとした理由があって、ある条件を指定して、それが合致したときに書き換え可能にできるというシチュエーションで使えるようにできるんです。
具体的には、パスワードを入力して、あっていれば変更できるというようなパターンです。
class Car:
def __init__(self, name='NXS', auto_drive=False, passwd='123'):
self.model = name
self._drive = auto_drive
self.passwd = passwd
@property
def drive(self):
return self._drive
@drive.setter
def drive(self, is_enable):
if self.passwd == '234':
self._drive = is_enable
else:
raise ValueError
car = Car('NSX', passwd='234')
print(car.model)
car.drive = True
print(car.drive)
出力結果
NXS
True
2行目の初期設定にpasswd='123'
を付け加えて、5行目でクラス変数にpasswd
を指定します。
次にsetter
の13行目で、passwd
が234
の場合は変数is_enable
に書き換え可能にして、それ以外の場合はValueError
を返すように指定しています。
car
インスタンスを生成する際に引数に正しいpasswd
を入れているので、20行目でクラス変数のcar.drive
をTrue
に書き換えることができて、最後にTrue
と出力されます。
ただ、car._drive
は書き換え可能なので、20行目をcar._drive = True
と変更した場合、passwd
が間違っていようが、直接_drive
を指定しているので、True
に書き換えられてしまい、この場合も、最後のcar.drive
の出力結果は、True
になってしまいます。
クラス定義の外から隠す
_
と@property
を使って、クラス変数を読み込み専用にしたとしても、直接_
をつけてクラス変数を指定すれば、書き換えが可能になってしまいます。
クラス定義の外からクラス変数を書き換えられないようにするためには、頭に__(アンダースコア2つ)
をつけることで、クラス定義の外からは存在しない変数にすることができます。
なので、インスタンス生成後に触られたくないという場合は__(アンダースコア・アンダースコア)
をつけて、外部からアクセスできないようにします。
class Car:
def __init__(self, name='NXS', auto_drive=False):
self.model = name
self.__drive = auto_drive
@property
def drive(self):
return self.__drive
@drive.setter
def drive(self, is_enable):
self.__drive = is_enable
car = Car()
print(car.__drive)
エラー結果
AttributeError: 'Car' object has no attribute '__drive'
4,8,12行目に__
をつけて、クラス定義の外からはアクセスできないようにしています。
なので、さわられたくない度数!?でかんがえると
__
> _
> そのまま
という感じです。
こんがらがってくる
今回も色々試して、頭がこんがらがっています。
確かに、クラスの外からprint
出力で、__drive
を出力しようとするとアクセスできないのですが、car.__drive = True
と記述するとエラーが起こらなかったりするんです。
で、car.__drive
を出力するとTrue
になってるんですが、car.drive
はFalse
のままだったり、よくわからなくなってしまいます。
より具体的な使い方が見えてくると、これがこうで、あれがこうなので、それでいいんだとわかるようになるのかもしれませんが、今の時点ではちょっとこんがらがっています。
ま〜、このまま悩み続けていても前に進めないので、このような使い方があるということを頭に入れて次のレクチャーに進もうと思います。
それでは、明日もGood Python!