python __getattr__ 和__dict __, hasattr属性的用法

1.python __getattr

class adaptee(object):
    def foo(self):
        print('foo in adaptee')
        
    def bar(self):
        print('bar in adaptee')


class adapter(object):
    def __init__(self):
        self.adaptee = adaptee()

    def foo(self):
        print('foo in adapter')
        self.adaptee.foo()

    def __getattr__(self, name):
        return getattr(self.adaptee, name)


if __name__ == '__main__':
    a = adapter()
    a.foo()
    a.bar()

打印结果:
foo in adapter
foo in adaptee
bar in adaptee

2.python dict
类或对象中的所有属性----类的实例属性属于对象;类中的类属性和方法等属于类,即:

class Province(object):
    country = 'china'

    def __init__(self, name, count):
        self.name = name
        self.count = count

    def func(self, *args, **kwargs):
        print('func')


# 获取类的属性, 即:类属性,方法
print(Province.__dict__)
# 获取对象obj1的属性
obj1 = Province('山东', 10000)
print(obj1.__dict__)

打印结果
{‘dict’: <attribute ‘dict’ of ‘Province’ objects>, ‘module’: ‘main’, ‘weakref’: <attribute ‘weakref’ of ‘Province’ objects>, ‘country’: ‘china’, ‘doc’: None, ‘func’: <function Province.func at 0x000001D06BE7D048>, ‘init’: <function Province.init at 0x000001D06BE70F28>}
{‘count’: 10000, ‘name’: ‘山东’}

3.python hasattr
hasattr()函数用于判断对象是否包含对应的属性,hasattr(object, name)

class Coordinate(object):
    x = 10
    y = -5
    z = 0

point1 = Coordinate()
print(hasattr(point1, 'x'))
print(hasattr(point1, 'y'))
print(hasattr(point1, 'z'))
print(hasattr(point1, 'no'))

打印结果
True
True
True
False

4.魔方方法
*1.getattr(self, name):访问不存在的属性时调用
2.getattribute(self, name):访问存在的属性时调用(先调用该方法,查看是否存在该属性,若不存在,接着去调用1)
3.setattr(self, name, value):设置实例对象的一个新的属性时调用
4.delattr(self, name):删除一个实例对象的属性时调用
*

### Python 中 `__del__` 方法引发 `TypeError: 'NoneType' object is not subscriptable` 的解决方案 当在 Python 类中定义 `__del__` 方法时,可能会遇到类似于 `'NoneType' object is not subscriptable` 的错误。这种错误通常发生在对象被销毁的过程中尝试访问已经被设置为 `None` 或已经删除的属性。 #### 错误分析 该问题的根本原因是,在对象生命周期结束时,Python 可能会先清理某些依赖资源或属性,而这些资源可能仍然在 `__del__` 方法中被引用[^1]。如果某个属性已被置为 `None` 或者其关联的对象已不存在,则任何对该属性的操作都会触发类似的错误。 此外,如果类中有自定义实现的 `_delattr_` 方法,并且其中存在递归调用逻辑(例如通过 `del self.name` 删除属性),也可能导致无限递归或其他未预期的行为[^2]。 --- #### 解决方案 以下是几种常见的解决策略: 1. **检查属性是否存在并验证类型** 在 `__del__` 方法中操作属性之前,应始终确认目标属性是否仍有效以及它的数据类型是否符合预期。可以使用内置函数 `hasattr()` `isinstance()` 来完成这一任务。 ```python class MyClass: expected_type = dict def __init__(self, value): self.value = value def __del__(self): if hasattr(self, "value") and isinstance(self.value, self.expected_type): # 验证属性有效性 try: keys = list(self.value.keys()) # 处理字典类型的值 for key in keys: del self.value[key] except TypeError as e: print(f"Error during deletion: {e}") @property def value(self): return getattr(self, "_value", None) @value.setter def value(self, new_value): if not isinstance(new_value, self.expected_type): raise ValueError("Value must be of type dictionary.") self._value = new_value ``` 2. **避免直接修改实例变量** 如果需要释放资源或者执行其他清理工作,建议尽量减少对实例变量的直接操作。可以通过局部变量保存临时状态来规避潜在的风险。 ```python class ResourceHandler: def __init__(self, resource=None): self.resource = resource or {} def __del__(self): local_resource = getattr(self, "resource", {}) if isinstance(local_resource, dict): for k in list(local_resource.keys()): local_resource.pop(k, None) # 安全移除键值对 ``` 3. **重写 `_delattr_` 并防止循环引用** 当覆盖默认行为时需格外小心,尤其是涉及删除成员变量的部分。为了预防可能出现的无限递归现象,可以在内部维护一个标志位记录当前所处的状态。 ```python class SafeDeletionClass: _deleting = False def __delattr__(self, name): if not self._deleting: self._deleting = True super().__delattr__(name) self._deleting = False else: pass # 跳过进一步处理以中断递归链路 def __del__(self): setattr(self, '_deleting', True) # 执行必要的清除动作... del self.some_attribute # 假设 some_attribute 是要删除的目标之一 ``` 4. **利用弱引用管理复杂场景下的对象关系** 对于那些容易形成强引用环从而阻碍垃圾回收机制正常工作的场合,考虑引入 [`weakref`](https://docs.python.org/zh-cn/3/library/weakref.html) 模块中的工具替代常规指针形式连接各个组件间的关系网状结构。 ```python import weakref class NodeWithWeakRef: def __init__(self, data, next_node=None): self.data = data self.next_ref = weakref.ref(next_node) if next_node else None @property def next(self): return self.next_ref() if self.next_ref else None def __repr__(self): return f"<Node({self.data})>" def __del__(self): print(f"{self} being deleted...") ``` --- ### 总结 上述方法分别针对不同层面提供了应对措施:从简单的属性校验到复杂的递归防护乃至高级别的内存优化技巧都有涵盖。实际应用过程中可根据具体情况灵活选用最合适的手段解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值