You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python子类化threading.Thread的属性命名规范及安全属性咨询

问题描述

我阅读了threading.Thread的文档,其中提到:

指定线程活动有两种方式:向构造函数传入可调用对象,或在子类中重写run()方法

我编写了如下测试程序:

class MyThread(threading.Thread):
    def __init__(self):
        super().__init__()
        self._started = False
    def run(self):
        self._started = True
obj = MyThread()
obj.start()
obj.join()
print(self._started)

但程序运行失败,报错信息如下:

$ python3 ./1.py 
Traceback (most recent call last):
  File "/dev/shm/.1000.home.tmp.dir/./1.py", line 10, in <module>
    obj.start()
  File "/usr/lib/python3.11/threading.py", line 951, in start
    if self._started.is_set():
       ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'is_set'

文档中并未提及_started是threading.Thread的内部属性,我有以下疑问:

  1. Python中是否存在关于实现保留字段的约定?
  2. 子类化threading.Thread时是否不应使用下划线开头的字段?
  3. 哪些属性是安全可设置的?
解答

1. Python中关于实现保留字段的约定

Python有明确的命名约定:

  • 单下划线开头的属性(如_x)属于内部实现细节,语法上不强制私有,但约定俗成是类内部使用的,子类和外部代码应避免直接访问或覆盖。
  • 双下划线开头且结尾无双下划线的属性(如__x)会触发名称修饰,Python会自动将其改为_类名__x,避免子类意外覆盖父类内部属性。
  • 前后双下划线的属性(如__init__)是Python特殊方法/属性,属于语言层面约定,不能随意使用。

这些规则在PEP 8规范中有明确说明,核心是用下划线区分「公开接口」和「内部实现」。

2. 子类化threading.Thread时是否不应使用下划线开头的字段

不是绝对不能用,但强烈不建议。threading.Thread内部会用到大量单下划线开头的属性(比如_started、_target、_args等),这些属性不会出现在公开文档中,但却是类正常运行的关键。

如果子类使用同名下划线属性,会直接覆盖父类内部属性,导致父类方法执行出错——就像你的代码中,父类start()方法期望_started是带is_set()方法的Event对象,你却把它改成布尔值,直接引发属性错误。

如果一定要用自定义内部属性,建议用双下划线开头的名称(如self.__started),触发名称修饰后会变成_MyThread__started,不会和父类的_started冲突。

3. 哪些属性是安全可设置的

threading.Thread的公开属性是文档明确列出的,这些可以安全访问或设置:

  • name:线程名称,可直接设置或读取
  • ident:线程标识符,只读
  • daemon:是否为守护线程,可在start()之前设置

另外,你可以安全添加自己的公开属性(不用下划线开头),比如self.started_flag = False,既不会和父类内部属性冲突,也符合命名规范。

重写run()方法是文档明确允许的,但要注意不要破坏父类初始化逻辑——你的代码中__init__调用super().__init__()是正确的,若要添加自定义属性,优先用非下划线开头的名称,或用双下划线避免冲突。


内容的提问来源于stack exchange,提问作者KamilCuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:22:35