Python学習【365日チャレンジ!】82日目のマスターU(@Udemy11)です。
少し前にスマホのキャリアを楽天モバイルに変更したのですが、やはりちょっとスピードが気になりますが、楽天会員であれば、1年間1,500円割引キャンペーンを利用しているので、めちゃくちゃ通信量が安くなりました。
以前は約5,000円程度だった月額料金が、
なんとびっくりの1,080円!!
楽天のダイヤモンド会員でもあるので、月額の割引金額は2,000円と超お得なんです。
通信スピードに不満がないわけではありませんが、自宅ではWifiにつなげれば問題ありませんし、外でそんなにヘビーな使い化をするわけではないので、コストパフォーマンスは最高です。
スマホの通信費が高いと頭を悩ませている場合は、ぜひ一度、楽天モバイルを検討してみてはどうでしょうか?
それではPython学習をすすめましょう。
昨日の復習
昨日は、プロパティーを使った属性の設定について学習しました。
class Car:
def __init__(self,name='Crown', 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)
出力結果
Crown
False
@property
を使って関数にすることで、drive
がクラス変数として扱われました。
そのクラス変数deive
の返り値を、Car
クラスで初期化した_drive
とすることで、クラスの外からはクラス変数drive
を書き換えられないようにすることができました。
また、@drive.setter
を指定して、書き換えられる条件を付け足すこともできましたね。
@property
による属性設定については、こちらの記事を参考にしてください。
それでは本日のPython学習をすすめましょう。
構造体とは
構造体とは何かをWikipediaで調べると次のような解説が見つかりました。
構造体とは
構造体(こうぞうたい、英: structure)はプログラミング言語におけるデータ型の一つで、1つもしくは複数の値をまとめて格納できる型。それぞれのメンバー(フィールド)は型が異なっていてもよい点が配列と異なる。
C/C++やC#などでstructとしてサポートされているほか、Visual Basicのユーザー定義型や、PascalやAdaのrecord型も構造体に相当する。
クラスベースのオブジェクト指向言語では、抽象データ型としてのクラスが構造体の役割をも内包する。Cの文法を継承した言語ではstructキーワードを含むこともあるが、言語によってその役割は異なる。
引用元: Wikipedia
他のプログラミング言語のことはよくわからないのですが、WikiではPythonについては書かれていませんでした。。
C言語などにおけるところの構造体はPythonにはありませんが、クラスが構造体の役割を担っているという感じです。
クラス変数の作成
Pythonには、データ構造体としてclass
があるわけですが、クラス内で定義する変数は、インスタンスを作成してから、追加することができます。
class Person:
pass
p = Person()
p.name = 'Mark'
p.age = 40
print(p.name, p.age)
出力結果
Mark 40
Person
クラスでは何もしないpass
を指定したあと、Person
のインスタンスp
を作成し、あとから、p.name
とp.age
というクラス変数を定義しています。
イメージとしては、設計図のキャンパスだけ用意して、あとから書き足していくような感じですね。
ある意味、便利な使い方なのですが、設計図(class
)を書いたプログラマーからするとちょっと困っちゃいますよね。
ということで、Python学習者なら知っておかないといけないクラスを扱う際の注意点について解説します。
クラスを扱う際の注意点
Pythonのクラスは、インスタンス作成後にクラス変数を作成することができるので、便利な半面、注意しなければいけないこともあります。
それが、クラス内で定義したクラス変数をオーバーライドできるというところです。
クラス内で定義された__(アンダースコア*2)
が付いた変数は、インスタンスからは呼び出せないことを昨日のレクチャーで学習しましたが、クラス変数名をそのまま指定して、値を定義すると、__(アンダースコア*2)
が付いていても上書きされてしまいます。
class Car:
def __init__(self, name='Crown', 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()
car.__drive = True
print(car.__drive)
print(car.drive)
出力結果
True
False
このコードでは、__drive
は、インスタンスcar
からは呼び出すことはできませんので、15行目にprint(car.__drive)
を挿入して実行するとAttributeError: ‘Car’ object has no attribute ‘__drive’というエラーが起こります。
しかし、上記コードの15行目のようにcar.__drive = True
と値を指定すると、クラス変数の値を上書きしちゃうんです。
とりあえず、昨日よくわからないままになっていた、クラスの外から見えないはずの__
で指定されたクラス変数の値が変更されてしまうという疑問はこれで解決できました。
オーバーライドの機能はかなり強力なので、もし、インスタンス内でクラス変数を定義する場合は、クラスの中で定義されている変数名と同じものではないかということをチェックしておく必要があります。
といっても、基本的にインスタンス内でクラス変数を作るのはあまりおすすめではないとのことでした。
ここで一つ疑問がのこるのは、car.drive
の値が置き換わらないということです。
上記コードで__drive
をすべて_drive
に変えると、最後の出力は、True
になります。
class Car:
def __init__(self, name='Crown', 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()
car._drive = True
print(car._drive)
print(car.drive)
出力結果
True
True
car.__drive
を上書きしても、car.drive
は変更されなかったのに、car._drive
にして、値を上書きしてしまうと、car.drive
の値は変更されてしまいます。
__drive
と_drive
とdrive
の関係を理解するためには、より詳しく調べる必要がありそうですが、いまは_drive
をオーバーライドするとdrive
も上書きされて、__drive
をオーバーライドした場合は、drive
は上書きされないと認識しておく程度でいいでしょう。
わからないことが増えてくる
講座が進むにつれて、どんどんわからないことが増えていきます。
わからないことは理解できるまで調べることが大切ですが、時間をかけて調べても理解できないことも増えてきます。
なので、ある程度の認識ができるようになったら、次に進むような柔軟な対応が必要になってきます。まさに、
トレードオフ
が必要だということですね。
こんなことがあったなという疑問として頭の片隅に残しておけば、具体的なプログラムを組むときにその疑問が解決するかもしれませんし、実際に使われることはないので全く気にする必要のないものかもしれません。
ときにはわからないことをすっ飛ばす勇気も必要ということです。
それでは、明日もGood Python!