python@propertyの使用

2933 ワード

引用-廖雪峰
背景
アトリビュートを設定するときは、アトリビュートを直接露出することができます.これは簡単ですが、アトリビュート値を勝手に変更することになります.
class Student(object):
    def __init__(self):
        self.score = 60

In [13]: student = Student()

In [15]: student.score
Out[15]: 60

In [16]: student.score=101

In [17]: student.score
Out[17]: 101

上記の値が勝手に変更されないように、関数を増やして判断し、属性値が有効かどうかを確認することができます.
class Student(object):
    def __init__(self):
        self.score = 60

    def get_score(self):
        return self.score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score %s must be an integer!' % value)
        if value < 0 or value > 100:
            raise ValueError('score %s must between 0 ~ 100!' % value)
        self.score = value

In [2]: student = Student()

In [3]: student.score
Out[3]: 60

In [4]: student.get_score()
Out[4]: 60

In [6]: student.set_score(95)

In [7]: student.score
Out[7]: 95

In [8]: student.get_score()
Out[8]: 95

In [9]: student.set_score(9.9)
---------------------------------------------------------------------------
... ...
ValueError: score 9.9 must be an integer!

In [10]: student.set_score(101)
---------------------------------------------------------------------------
... ...
ValueError: score 101 must between 0 ~ 100!

しかし、上記の使い方は複雑ですが、pythonはこの機能を実現する方法がありますか?はい、Python内蔵の@property装飾器です@propertyデコレーションを使用
class Student(object):
    def __init__(self):
        self.score = 60

    @property
    def student_score(self):  # student_score       score      
        return self.score

    @student_score.setter
    def student_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score %s must be an integer!' % value)
        if value < 0 or value > 100:
            raise ValueError('score %s must between 0 ~ 100!' % value)
        self.score = value
@propertyを加えて、getterメソッドを属性にします.@property自体は、setterメソッドを属性付与に変更する役割を果たす別の装飾器@student_score.setterを作成し、制御可能な(メソッドが属性になる)操作を有している.
In [5]: student = Student()

In [6]: student.score
Out[6]: 60

In [7]: student.student_score
Out[7]: 60

In [8]: student.student_score = 95

In [9]: student.score
Out[9]: 95

In [10]: student.student_score
Out[10]: 95

In [11]: student.student_score = 9.5
---------------------------------------------------------------------------
... ...
ValueError: score 9.5 must be an integer!

In [12]: student.student_score = 101
---------------------------------------------------------------------------
... ...
ValueError: score 101 must between 0 ~ 100!

読み取り専用プロパティを定義することもできます.getterメソッドのみを定義し、setterメソッドを定義しないのは読み取り専用プロパティです.
まとめ@propertyはクラスの定義に広く適用され、呼び出し者に短いコードを書かせるとともに、パラメータの必要なチェックを保証することができ、プログラムの実行時にエラーの可能性を減らすことができる.