<jupyter_start><jupyter_text>属性描述符> 学会描述符之后，不仅有更多的工具集可用，还会对 Python 的运作方式有更深入的理解，并由衷赞叹 Python 设计的优雅。  > ——<NAME>, Python 核心开发者和专家本章的话题是描述符。  描述符是实现了特定协议的类，这个协议包括 `__get__`、`__set__`、和 `__delete__` 方法。有了它，我们就可以在类上定义一个托管属性，并把所有对实例中托管属性的读写操作交给描述符类去处理。<jupyter_code># 描述符示例：将一个属性托管给一个描述符类
class CharField:                       # 描述符类
    def __init__(self, field_name):
        self.field_name = field_name

    def __get__(self, instance, storage_cls):
        print('__get__', instance, storage_cls)
        if instance is None:            # 直接在类上访问托管属性时，instance 为 None
            return self
        return instance[self.field_name]

    def __set__(self, instance, value):
        print('__set__', instance, value)
        if not isinstance(value, str):
            raise TypeError('Value should be string')
        instance[self.field_name] = value


class SomeModel:                         # 托管类
    name = CharField('name')             # 描述符实例，也是托管类中的托管属性

    def __init__(self, **kwargs):
        self._dict = kwargs              # 出巡属性，用于存储属性

    def __getitem__(self, item):
        return self._dict[item]

    def __setitem__(self, item, value):
        self._dict[item] = value



print(SomeModel.name)
d = SomeModel(name='some name')
print(d.name)
d.name = 'another name'
print(d.name)
try:
    d.name = 1
except Exception as e:
    print(repr(e))<jupyter_output>__get__ None <class '__main__.SomeModel'>
<__main__.CharField object at 0x063AF1F0>
__get__ <__main__.SomeModel object at 0x063AF4B0> <class '__main__.SomeModel'>
some name
__set__ <__main__.SomeModel object at 0x063AF4B0> another name
__get__ <__main__.SomeModel object at 0x063AF4B0> <class '__main__.SomeModel'>
another name
__set__ <__main__.SomeModel object at 0x063AF4B0> 1
TypeError('Value should be string')
{'fraction_non_alphanumeric': 0.09983268265476855, 'fraction_numerical': 0.01784718349135527, 'mean_word_length': 3.407862407862408, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '461688', 'license': 'MIT', 'n_tokens_mistral': 754, 'n_tokens_neox': 791, 'n_words': 140, 'path': '20-descriptor.ipynb', 'repo_name': 'yuechuanx/fluent-python-code-and-notes', 'size': '1804'}