Python中member_descriptor是什么?如何访问/修改其内容(Python3.6示例)
理解Python中的member_descriptor
咱们先从定义说起:member_descriptor是CPython解释器的内部类型,专门用来处理由C语言实现的扩展类的成员属性。你可以把它看作是C扩展版本的property——它负责定义这些属性的访问、读取和修改规则,是底层C代码和Python层交互的桥梁。
你给出的示例正好能说明这一点:
In [1]: import _pickle In [2]: _pickle.Pickler.dispatch_table Out[2]: <member 'dispatch_table' of '_pickle.Pickler' objects> In [3]: type(_pickle.Pickler.dispatch_table) Out[3]: member_descriptor
这里_pickle.Pickler是用C实现的扩展类,它的dispatch_table属性就由member_descriptor来描述。
如何访问member_descriptor对应的属性内容
访问分为两种场景:
- 类级别访问:直接通过类名访问(比如
_pickle.Pickler.dispatch_table),得到的是member_descriptor对象本身,它只是告诉你这个属性属于哪个类,并不是实际的属性值。 - 实例级别访问:创建类的实例后,通过实例访问该属性,就能拿到它的实际值。比如:
# 创建Pickler实例 pickler = _pickle.Pickler(open('temp.pkl', 'wb')) # 访问实例的dispatch_table,得到实际的字典值 print(pickler.dispatch_table)
如何修改member_descriptor对应的属性内容
修改也分两种情况,需要根据你的需求选择:
- 仅修改单个实例的属性
直接给实例的属性赋值即可,这个修改只会影响当前实例,不会改变其他实例的默认值:
import _pickle import copyreg # 定义一个自定义的整数处理函数 def custom_int_handler(obj): return int, (obj,) # 创建实例 pickler = _pickle.Pickler(open('temp.pkl', 'wb')) # 修改当前实例的dispatch_table pickler.dispatch_table = copyreg.dispatch_table.copy() pickler.dispatch_table[int] = custom_int_handler
- 修改类的默认属性值(影响所有新实例)
直接给类的属性赋值,这样后续创建的所有实例都会使用这个修改后的默认值。不过要注意:有些member_descriptor对应的属性是只读的,强行赋值会抛出AttributeError,需要先测试是否支持修改:
import _pickle import copyreg def custom_int_handler(obj): return int, (obj,) # 修改类级别的dispatch_table,后续新实例都会继承这个设置 _pickle.Pickler.dispatch_table = copyreg.dispatch_table.copy() _pickle.Pickler.dispatch_table[int] = custom_int_handler # 新创建的实例会使用修改后的dispatch_table new_pickler = _pickle.Pickler(open('new_temp.pkl', 'wb')) print(new_pickler.dispatch_table[int]) # 输出自定义的处理函数
如果遇到赋值报错,说明该属性是只读的,无法在类级别修改,只能修改单个实例的属性(如果实例允许的话)。
内容的提问来源于stack exchange,提问作者Saim Raza
相关产品推荐
相关产品推荐

