Python 特殊方法:属性访问与描述符的深度剖析
全面解读属性访问与描述符相关特殊方法__getattr__、__setattr__、__delattr__、__getattribute__ 以及描述符相关的 __get__、__set__、__delete__、__set_name__、__getstate__ 和 __setstate__ 方法。通过示例展示如何利用这些方法实现属性的动态访问、赋值验证、删除控制以及对象的序列化和反序列化。
- _getattr_****方法:当访问对象不存在的属性时被调用,可用于实现动态属性或提供默认值。例如,当访问一个不存在的属性时,返回一个固定的默认值:
class DynamicAttr:
    def __getattr__(self, name):
        if name == 'default_attr':
            return 'default value'
        raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
obj = DynamicAttr()
print(obj.default_attr)
- _setattr_****方法:在设置对象属性时调用,可用于对属性赋值进行拦截和验证。例如,限制某个属性只能设置为特定类型的值:
class ValidatedAttr:
    def __setattr__(self, name, value):
        if name == 'age' and not isinstance(value, int):
            raise ValueError('Age must be an integer')
        super().__setattr__(name, value)
obj = ValidatedAttr()
obj.age = 25
- _delattr_****方法:在删除对象属性时调用,可用于实现属性删除的自定义逻辑。例如,在删除属性时记录日志:
import logging
class LoggedAttr:
    def __delattr__(self, name):
        logging.info(f"Deleting attribute {name}")
        super().__delattr__(name)
obj = LoggedAttr()
obj.attr = 10
del obj.attr
- _getattribute_****方法:在访问对象任何属性时都会调用,比 getattr 更优先,需谨慎使用以避免无限递归。例如:
class AllAttrAccess:
    def __getattribute__(self, name):
        print(f"Accessing attribute {name}")
        return super().__getattribute__(name)
obj = AllAttrAccess()
obj.some_attr = 10
print(obj.some_attr)
- 
描述符相关方法: 
- 
_get_****方法:用于获取描述符管理的属性值。 
- 
_set_****方法:用于设置描述符管理的属性值。 
- 
_delete_****方法:用于删除描述符管理的属性时的逻辑处理。 
- 
_set_name_****方法:Python 3.6 及以上版本新增,描述符被赋值给类的属性时调用,可获取所属类和属性名。 
- 
示例:通过描述符实现一个属性的验证和管理: 
class ValidatedDescriptor:
    def __set_name__(self, owner, name):
        self.name = name
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)
    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise ValueError(f"{self.name} must be an integer")
        instance.__dict__[self.name] = value
class MyClass:
    validated_attr = ValidatedDescriptor()
obj = MyClass()
obj.validated_attr = 10
- _getstate_和setstate****方法:用于对象的序列化和反序列化,分别在对象被 pickle 时获取和恢复对象状态。例如,在序列化时,将某些敏感信息排除:
import pickle
class SensitiveData:
    def __init__(self):
        self.normal_data = 'normal'
        self.sensitive_data ='sensitive'
    def __getstate__(self):
        state = self.__dict__.copy()
        del state['sensitive_data']
        return state
    def __setstate__(self, state):
        self.__dict__.update(state)
obj = SensitiveData()
serialized = pickle.dumps(obj)
deserialized = pickle.loads(serialized)
print(deserialized.normal_data)
- 
参考资料:参考 Python 官方关于描述符的文档(https://docs.python.org/3/howto/descriptor.html ),结合 Tekin 的 Python 专栏中数据结构相关文章(https://blog.csdn.net/tekin_cn/article/details/145597396),分析这些方法在不同数据结构中的应用场景,帮助读者掌握属性管理的高级技巧。 
- 
总结:梳理属性访问与描述符特殊方法的使用要点,强调其对提升代码可维护性和健壮性的重要意义。 
- 
TAG:Python、特殊方法、属性访问、描述符、序列化 
 
                    
                     
                    
                 
                    
                 
                
 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号