python 类中的方法互相调用为什么是self.function()形式

本文通过一个具体的Python代码示例,解释了在类中定义方法时使用self参数的重要性。self参数允许方法访问类的实例变量和其他方法,而没有self的方法可能会执行类外部的同名函数,导致意外的行为。

 因为,不加self, 你可能会执行类外的同名函数eat

def eat(thing):
    print(thing,'--->执行了类外函数')


class Dog:

    def eat(self, thing):
        print('执行了类内函数', thing)

    def run(self):
        eat(2)

Dog().run()

结果:

再看看加个self的情况:

<think>根据用户的问题,用户想了解Python中与`target=self.run`相关的函数或方法,这通常出现在多线程编程中,尤其是在使用`threading`模块创建线程时。在`threading.Thread`的初始化中,`target`参数用于指定线程启动时调用的函数,而如果使用`target=self.run`,则通常是在自定义线程中重写了`run`方法,并将线程的目标设置为这个自定义的`run`方法。 下面我将详细解释相关概念和用法,并参考提供的引用内容。 ### 1. `threading.Thread`的基本用法 在Python中,创建线程的一种方式是实例化`threading.Thread`,并传递`target`参数(一个可调用对象)和`args`(可选的参数元组)。当线程启动时,会调用`target`指定的函数。 例如: ```python import threading def my_function(arg): print(f"Thread running with arg: {arg}") # 创建线程,target指向函数my_function thread = threading.Thread(target=my_function, args=("hello",)) thread.start() ``` ### 2. 自定义线程重写`run`方法 另一种方式是创建`threading.Thread`的子,并重写`run()`方法。这样,当线程启动时,会自动调用的`run`方法。此时,在创建线程实例时,不需要指定`target`,因为线程执行的就是`run`方法。 参考引用[3]中的例子: ```python import threading class MyThread(threading.Thread): def __init__(self, msg): super().__init__() self.msg = msg def run(self): # 重写run方法 while True: print(self.msg) # 创建线程实例并启动 test = MyThread('hello') test.start() ``` ### 3. 使用`target=self.run`的情况 如果我们在自定义中定义了一个`run`方法(注意不是重写`threading.Thread`的`run`方法),然后创建线程时设置`target=self.run`,那么线程将执行这个自定义的`run`方法。但这种情况通常不是自定义线程,而是将线程作为另一个的一部分(即在一个非线程中使用线程)。 例如: ```python import threading import time class Worker: def __init__(self): self.thread = threading.Thread(target=self.run) # 设置target为自身的run方法 def run(self): # 自定义的run方法 print("Worker thread started") time.sleep(1) print("Worker thread finished") def start(self): self.thread.start() # 使用 worker = Worker() worker.start() ``` ### 4. 线程的停止控制 在线程中,我们通常需要一个退出机制。引用[1]中展示了一种通过事件(`Event`)来控制线程退出的方法: ```python import threading import time class StoppableThread(threading.Thread): def __init__(self): super().__init__() self._stop_event = threading.Event() def run(self): while not self._stop_event.is_set(): print("Thread is running...") time.sleep(1) def stop(self): self._stop_event.set() # 创建并启动线程 t = StoppableThread() t.start() time.sleep(3) t.stop() # 停止线程 ``` ### 5. 线程池中的使用 引用[2]展示了一个简单的线程池实现,其中线程的目标函数是在创建线程时通过`target`参数传递的。在下面的代码片段中,线程池中的每个线程执行时都会调用`func`函数: ```python class ThreadPool(object): def __init__(self, max_num=20): self.queue = queue.Queue(max_num) for i in range(max_num): self.queue.put(threading.Thread) def get_thread(self): return self.queue.get() def add_thread(self): self.queue.put(threading.Thread) pool = ThreadPool(10) def func(arg, p): print(arg) time.sleep(1) p.add_thread() for i in range(30): Thread = pool.get_thread() t = Thread(target=func, args=(i, pool)) # 设置target为func t.start() ``` ### 6. 注意事项 - 当使用`target=self.run`时,要确保`self.run`是一个可调用方法,并且注意`self`的绑定关系。 - 在多线程编程中,要注意线程安全,避免资源竞争。 ### 总结 `target=self.run`通常出现在以下两种场景: 1. 在一个非线程(如一个工作器)中,将线程的目标方法设置为当前实例的`run`方法。 2. 在自定义线程中,我们通常重写`run`方法,而无需设置`target`,因为基`Thread`已经将`run`作为线程的入口点。 用户可以根据实际需求选择合适的方式。如果希望直接控制线程的执行函数,可以使用`target`参数;如果希望封装线程的行为,可以继承`Thread`并重写`run`方法。 §§相关问题§§ 1. Python中如何停止一个正在运行的线程? 2. 多线程编程中如何避免资源竞争? 3. 线程池的作用是什么?如何实现一个线程池? 4. 自定义线程时,除了重写run方法,还可以重写哪些方法? 5. Python的threading模块中,守护线程(daemon thread)和非守护线程有什么区别?</think>### Python 中 `target=self.run` 相关函数与方法详解 在 Python 多线程编程中,`target=self.run` 通常用于指定线程执行的目标函数。核心涉及 `threading.Thread` 的用法,以下是关键知识点: #### 1. **基本用法** `threading.Thread` 的 `target` 参数指定线程启动时调用的函数。`self.run` 表示调用当前对象的 `run()` 方法: ```python import threading class MyThread: def run(self): print("线程执行中...") # 创建线程实例 obj = MyThread() thread = threading.Thread(target=obj.run) # target指向对象的run方法 thread.start() ``` #### 2. **继承 `Thread` 重写 `run()`** 更常见的方式是直接继承 `threading.Thread` 并重写 `run()` 方法(无需显式指定 `target`): ```python class CustomThread(threading.Thread): def __init__(self, msg): super().__init__() self.msg = msg def run(self): # 重写run方法 while True: print(self.msg) # 实际线程逻辑[^3] # 启动线程 t = CustomThread("Hello") t.start() ``` #### 3. **动态控制线程终止** 通过 `threading.Event` 实现安全终止: ```python class StoppableThread(threading.Thread): def __init__(self): super().__init__() self.stop_event = threading.Event() def run(self): while not self.stop_event.is_set(): print("运行中...") time.sleep(1) def stop(self): self.stop_event.set() # 触发停止[^1] ``` #### 4. **线程池中的 `target` 应用** 在线程池中动态分配目标函数: ```python import queue class ThreadPool: def __init__(self, max_workers=10): self.queue = queue.Queue() for _ in range(max_workers): self.queue.put(threading.Thread) # 预存线程 def execute(self, func, args): thread_class = self.queue.get() thread = thread_class(target=func, args=args) # 动态设置target thread.start() self.queue.put(thread_class) # 回收线程[^2] ``` #### 5. **关键注意事项** - **`target` 与 `run()` 关系**:未重写 `run()` 时,`target` 指定的函数会作为线程入口;重写后则以 `run()` 为准。 - **绑定方法**:`target=self.run` 确保方法绑定到当前对象实例,避免参数传递错误。 - **停止机制**:避免强制终止线程,推荐用 `Event` 或标志位实现协作式停止[^1]。 ### 典型错误示例 ```python # 错误:未绑定方法,导致缺少self参数 t = threading.Thread(target=MyThread.run) # 缺少实例! # 正确:通过实例绑定方法 obj = MyThread() t = threading.Thread(target=obj.run) # 绑定实例方法 ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值