鬼少 发表于 2024-10-16 22:54:12

关于python的属性名与方法名相同时, 属性会覆盖方法疑问

本帖最后由 鬼少 于 2024-10-16 22:55 编辑

有如下一段代码:
import time as t

class MyTimer():
      
    def __str__(self):
      return self.prompt

    __repr__ = __str__
   
    #开始计时
    def start(self):
      self.start = t.localtime()
      print('开始计时.....')
    #计时结束
    def stop(self):
      self.stop = t.localtime()
      self._calc()
      print('计时结束!')


    #内部方法,计算运行时间
    def _calc(self):
      self.lasted = []
      self.prompt = '总共运行了'
      for i in range(6):
            self.lasted.append(self.stop - self.start)
            self.prompt +=str(self.lasted)
      #print(self.prompt)

当执行如下代码时:
>>t1 = MyTimer()
>>t1.start()
开始计时.....
>>t1.start
time.struct_time(tm_year=2024, tm_mon=10, tm_mday=16, tm_hour=22, tm_min=48, tm_sec=56, tm_wday=2, tm_yday=290, tm_isdst=0)
>>t1.stop()
计时结束!
>>t1.stop
time.struct_time(tm_year=2024, tm_mon=10, tm_mday=16, tm_hour=22, tm_min=49, tm_sec=8, tm_wday=2, tm_yday=290, tm_isdst=0)

当执行t1.start, 此时的类属性start与方法start()同名,属性应该覆盖方法, 那为何此时调用t1.start()不报错误?

FishC 发表于 2024-10-16 22:54:31

在 Python 中,当一个实例属性与实例方法重名时,实例属性会覆盖方法,导致该方法无法通过实例直接调用。不过,由于某些原因,你在代码中没有遇到直接报错。

### 为什么调用 `t1.start` 才不报错?

1. **属性覆盖方法**: 当你在 `start` 方法中设定 `self.start = t.localtime()` 时,你把实例方法 `start()` 被 `self.start` 这个实例属性覆盖掉了。所以之后的`print(t1.start)`实际上是在访问这个实例属性,而不是调用方法。

2. **访问属性**: 当你输入 `t1.start` 时,你并没有尝试调用 `start()` 方法,而是直接访问了被覆盖的属性 `self.start`。这就是为什么没有出现报错,而是显示了时间数据。

### 为什么对 `t1.start()` 没有影响?

- 你在首次调用 `t1.start()` 时,`start()` 方法能正常执行,因为在这个方法中 `self.start` 还没有被属性覆盖。

### 如何避免这种问题?

- 为了避免属性与方法同名问题,推荐使用不同的命名规则,比如加上前缀、后缀(如 `_start_time`、`start_timer`),或通过“私有属性”命名 (如 `self._start`),这可以避免不小心覆盖方法。

在 Python 中,良好的命名习惯不仅能避免易错的重名问题,也能提升代码可读性哦。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 关于python的属性名与方法名相同时, 属性会覆盖方法疑问