一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して9日目です。クリックしてイベントの詳細をご覧ください。
Pythonの動的属性の概念はインタビューで尋ねられることがあり、プロジェクトでも非常に実用的ですが、一般的なプログラミングチュートリアルでは言及されないため、学ぶことができます。
簡単な例から始めましょう。Studentクラスを作成し、インスタンスを介して、名前、成績など、各学生に関する情報を取得したいと思います。試験が終了するまで成績は利用できないため、インスタンス化されたときに値が割り当てられることはありません。
class Student:
def __init__(self, name):
self.name = name
self.score = None
mike = Student('mike')
复制代码
試験後、マイクを評価する準備をします。
mike.score = 999
复制代码
ここで、教師が誤って追加の9を入力しました。一般的に、スコアは100ポイントです。999は不正なデータであるため、正常に割り当てることはできません。生徒の数が増えると、教師は得点の間違いを増やすことになります。そのため、得点の値を0〜100ポイントに制限するようにプログラムを変更する方法を見つける必要があります。
限界値
メソッドを定義します。入力が0〜100の整数でない場合は、プログラムにエラーを報告させ、データは有効であり、スコア属性を正常に変更します。
def set_score(self, new_score):
if not isinstance(new_score, int):
raise ValueError('score must be int')
if 0 <= new_score <= 100:
self.score = new_score
return self.score
else:
raise ValueError('score invalid')
复制代码
このように、スコアを取得する必要があるたびにself.scoreを使用して取得し、スコアを変更するときに関数を呼び出して変更します。
mike.set_score(999)
复制代码
999は不正なデータであるため、呼び出し後にエラーが報告されます。現時点では、self.scoreを使用して設定でき、エラーは報告されないことに注意してください。
self.score = 999
复制代码
これは明らかに機能しません。そのため、スコアを外部からアクセスできない私有財産に変えるメカニズムを提供する必要があります。残念ながら、Pythonのプライベートプロパティは疑似プライベートです。通常、属性はプライベート属性で_
始まりますが、これは単なるプロトコルと規制です。アンダースコアで始まる属性が表示された場合は、それらにアクセスしないでください。主張すればアクセスできますが、Pythonはそれを禁止しません。
代わりに@propertyを使用してください。
上記のメソッドは関数を実装しますが、属性の使用方法を変更します。通常、次のように使用されます。
# 获取属性
a = mike.score
# 设置属性
mike.score = 99
@property
def score(self):
return self._score
@score.setter
def score(self, new_score):
if not isinstance(new_score, int):
raise ValueError('score must be int')
if 0 <= new_score <= 100:
self._score = new_score
return self._score
else:
raise ValueError('score invalid')
复制代码
動的プロパティの利点
- 呼び出しメソッドが統一されています。関数呼び出しの方法ではなく、self.score=99の方法。
_score
直接使用することはありません。使用できますが、お勧めしません。- 読み取りのみが可能なプロパティがある場合は、セッター部分をコメントアウトするだけです。
次に、出生と年齢のプロパティを追加して、クラスを完了しましょう。
from datetime import datetime
class Student:
def __init__(self, name, birth=1920):
self.name = name
self._score = None
self.birth = birth
self.age = datetime.now().year - self.birth
mike = Student('mike')
print(mike.birth)
print(mike.age)
复制代码
-
出生と年齢はどちらか一方から計算できます。データの冗長性の問題があります。
-
年齢特性はこのように問題があります。マイクが初期化されたとき、年齢はすでに計算されています。来年、年齢プロパティにアクセスすると、間違った値になります。これは、ageを現在の秒数に設定することで確認できます。
self.age = datetime.now().second mike = Student('mike') time.sleep(5) print(mike.age) print(datetime.now().second) 复制代码
ダイナミックディスプレイ
@property
def age(self):
return datetime.now().year - self.birth
复制代码
@ age.setterは動的に変更されるため、ここでは設定しないでください。変更すると、データの不整合が発生します。読み取り専用プロパティとしてのみ使用できます。
@propertyの役割とアプリケーションのシナリオ:
- @propertyは、プロパティの読み取りと設定の読みやすさを最適化します
- 属性を制限する必要がある機能。
- 読み取り専用プロパティ。プロパティが読み取りのみで書き込みができない場合は、非常に便利です。
- このプロパティは、環境の変化に応じて動的に変化します。