Effective Python 讀書筆記: 第31條: 用描述符來該寫需要複用的@property方法

# -*- encoding: utf-8 -*-

import weakref

'''
第31條: 用描述符來該寫需要複用的@property方法

關鍵:
1 @property
缺點: 不便於複用,受它修飾的方法無法被同一個類中其他屬性複用,
與之無關的類也無法複用這些方法

2 描述符
描述符類: 可以提供__get__和__set__方法
原理: 
exam.writingGrade = 40
會被轉換爲
Exam.__dict__['writingGrade'].__set__(exam, 40)
獲取屬性會被轉換爲
Exam.__dict__['writingGrade'].__get__(exam, Exam)
之所以存在上述轉換: 是因爲object類的__getattribute__方法

類實例沒有某個屬性 ---> 在類中查找同名屬性(
類屬性,如果實現了__get__和__set__方法,則認爲該對象遵循描述符協議)

3 weakref
含義:提供WeakKeyDictionary的特殊字典
特點:如果運行系統發現這種字典所持有的引用是整個程序裏面執行Exam
實例的最後一份引用,那麼系統就會將實例從字典的鍵中移除。

4 總結
1) 複用@property方法及其驗證機制,用自己定義描述符類
2) WeakKeyDictionary保證描述符類不會泄露內存

參考:
Effectiv Python 編寫高質量Python代碼的59個有效方法
'''

# class Grade(object):
#     def __init__(self):
#         self._value = 0
#
#     def __get__(self, instance, instance_type):
#         return self._value
#
#     def __set__(self, instance, value):
#         if not (0 <= value <= 100):
#             raise ValueError('Grade must be between 0 and 100')
#         self._value = value


class Grade(object):
    def __init__(self):
        self._values = weakref.WeakKeyDictionary()

    def __get__(self, instance, instance_type):
        if instance is None:
            return self
        return self._values.get(instance, 0)

    def __set__(self, instance, value):
        if not (0 <= value <= 100):
            raise ValueError('Grade must be between 0 and 100')
        self._values[instance] = value


class Exam(object):
    mathGrade = Grade()
    writingGrade = Grade()
    scienceGrade = Grade()


def useExam():
    exam = Exam()
    exam.writingGrade = 82
    exam.scienceGrade = 99
    print exam.writingGrade
    print exam.scienceGrade
    secondExam = Exam()
    secondExam.writingGrade = 75
    print "First writing grade: {value}".format(
        value=exam.writingGrade
    )
    print "Second writing grade: {value}".format(
        value=secondExam.writingGrade
    )


def process():
    useExam()


if __name__ == "__main__":
    process() 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章