angel_wy 发表于 2025-7-9 15:24:28

关于python的习题求助

题目:编写一个 Counter 类,用于实时检测对象有多少个属性。
程序实现如下
>>> c = Counter()
>>> c.x = 1
>>> c.counter
1
>>> c.y = 1
>>> c.z = 1
>>> c.counter
3
>>> del c.x
>>> c.counter
2

小甲鱼的答案:
>>> class Counter:
      k = []
      def __init__(self):
                self.counter = 0
      def __setattr__(self, name, value):
                if name != 'counter':
                        if name not in self.k:
                              self.counter += 1
                              self.k.append(name)
                super().__setattr__(name, value)
      def __delattr__(self, name):
                self.counter -= 1
                self.k.remove(name)
                super().__delattr__(name)

我的答案:
class Counter:
    def __init__(self):
      self.counter = 0

    def __getattribute__(self, name):
      if name == "counter":
            return len(self.__dict__) - 1
      else:
            return super().__getattribute__(name)
请问我的答案和小甲鱼相比有什么问题?我运行也正常

FishC 发表于 2025-7-9 15:29:11

你的代码思路很巧妙,但存在几个关键问题:

### 主要问题分析:
1. **无限递归风险**:
   - 在 `__getattribute__` 中直接使用 `self.__dict__` 会导致无限递归
   - 正确做法:通过 `super()` 获取基类的属性

2. **counter属性被覆盖**:
   - 初始化时 `self.counter = 0` 存储了值
   - 但访问时总是返回动态计算值,用户无法实际存储数据到 `counter`

3. **特殊属性破坏计数**:
   - 如果用户设置 `__dict__` 属性会破坏整个计数逻辑
   - 例如执行 `c.__dict__ = {}` 后计数会出错

### 修正后的代码建议:
class Counter:
    def __init__(self):
      # 使用父类方法设置初始属性
      super().__setattr__('counter', 0)
   
    def __getattribute__(self, name):
      if name == "counter":
            # 安全获取__dict__避免递归
            d = super().__getattribute__('__dict__')
            return len(d) - 1# 排除counter自身
      return super().__getattribute__(name)
   
    def __setattr__(self, name, value):
      if name == "counter":
            return# 屏蔽对counter的修改
      super().__setattr__(name, value)

### 小甲鱼代码的优化点:
1. 使用独立的存储列表 `k` 跟踪属性名
2. 通过 `__setattr__` 和 `__delattr__` 精确控制计数
3. 避免了对特殊属性(如 `__dict__`)的依赖

### 总结建议:
你的方案在简单场景可行,但健壮性不足。实际开发中更推荐小甲鱼的思路(需修正类属性 `k` 改为实例属性)。核心原则:
- 避免在 `__getattribute__` 中直接访问 `self.xxx`
- 需要处理属性删除和重复赋值的情况
- 防止用户修改计数器的存储机制

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

某一个“天” 发表于 2025-7-9 16:20:54

你的挺好的
页: [1]
查看完整版本: 关于python的习题求助