Python 对象在尝试定义线程时没有属性

Python 对象在尝试定义线程时没有属性,python,multithreading,Python,Multithreading,代码如下: class foo: def levelOne(self): def worker(self, i): print('doing hard work') def writer(self): print('writing workers work') session = foo() i=0 threads = list() for i in range(0,5): thread = th

代码如下:

class foo:
    def levelOne(self):
        def worker(self, i):
            print('doing hard work')
        def writer(self):
            print('writing workers work')

session = foo()

i=0
threads = list()
for i in range(0,5):
    thread = threading.Thread(target=session.levelOne.worker, args=(i,))
    thread.start()
    threads.append(thread)

writerThread = threading.Thread(target=session.levelOne.writer)
writerThread.start()

for thread in threads:
    thread.join()

writerThread.join()
5工人应该做这项工作,作者应该收集他们的结果

我得到的错误是:会话对象没有属性worker

工人实际上是测试人员,他们在不同的“领域”做某项工作,而作者则在跟踪他们,而不让我的工人返回任何结果。 将该算法划分为“levelOne”、“levelTwo”等层非常重要,因为它们将一起工作。这就是我将线程保留在类之外而不是levelOne方法的主要原因

请帮助我理解我的错误所在

您当然不会将“会话对象没有属性worker”作为错误消息,并附上您发布的代码-错误应该是“'function'对象没有属性'worker'”。事实上,我不知道你为什么会期望其他东西——函数中定义的名称是局部变量(提示:python函数和其他任何函数一样都是对象),它们不会成为函数的属性

将此算法划分为“一级”、“二级”等层非常重要

嗯,可能吧,但那不是正确的设计。如果您希望
foo
只是一个名称空间,
levelOne
levelTwo
等成为某种类型的实例,具有bot-a
writer
worker
方法,那么您需要1/将
LevelXXX
定义为类,2/将这些对象的实例构建为
foo
类的属性,即:

class LevelOne():
    def worker(self, i):
       # ...
    def writer(self):
       # ...


class foo():
    levelOne = LevelOne()
现在,这是否是适合您的用例的正确设计并没有任何保证,但在不了解任何问题的情况下,不可能设计出正确的解决方案

若可能的话,您能解释一下为什么试图访问问题代码中所示的工作人员和编写人员是糟糕的设计吗

好吧,仅仅因为它不起作用,首先,显然是xD

请注意,您可以从
levelOne
方法返回“worker”和“writer”函数,即:

class foo:
    def levelOne(self):
        def worker(self, i):
            print('doing hard work')
        def writer(self):
            print('writing workers work')

        return worker, writer


session = foo()
worker, writer = session.levelOne()

# etc
但这既复杂(假设重点是让
worker
writer
共享
self
,更简单的是使用适当的
LevelOne
类并使
worker
writer
方法来实现)又低效(
def
是一条可执行语句,因此在您的解决方案中,
worker
writer
函数会在每次调用时重新创建,这不是免费的)。

您肯定不会将“session object has no attribute worker”(会话对象没有属性工作者)作为错误消息,而您发布的代码则会显示错误“'function'对象没有属性'worker'”。事实上,我不知道你为什么会期望其他任何东西-函数中定义的名称是局部变量(提示:python函数和其他任何函数一样都是对象),它们不会成为函数的属性

将此算法划分为“一级”、“二级”等层非常重要

嗯,可能是这样,但这不是正确的设计。如果你想
foo
只是一个名称空间,而
levelOne
levelTwo
等是某种类型的实例,具有bot-a
writer
worker
方法,那么你需要1/将
LevelXXX
定义为类,2/构建ose对象作为
foo
类的属性,即:

class LevelOne():
    def worker(self, i):
       # ...
    def writer(self):
       # ...


class foo():
    levelOne = LevelOne()
现在,这是否是适合您的用例的正确设计并没有任何保证,但在不了解任何问题的情况下,不可能设计出正确的解决方案

若可能的话,您能解释一下为什么试图访问问题代码中所示的工作人员和编写人员是糟糕的设计吗

好吧,仅仅因为它不起作用,首先,显然是xD

请注意,您可以从
levelOne
方法返回“worker”和“writer”函数,即:

class foo:
    def levelOne(self):
        def worker(self, i):
            print('doing hard work')
        def writer(self):
            print('writing workers work')

        return worker, writer


session = foo()
worker, writer = session.levelOne()

# etc

但这既复杂(假设重点是让
worker
writer
共享
self
,更简单的是使用适当的
LevelOne
类并使
worker
writer
方法来实现)又低效(
def
是一条可执行语句,因此使用您的解决方案,
worker
writer
函数在每次调用时都会重新创建(这不是免费的).

可能重复我不认为这是一个解决方案,我不需要返回它的结果。我的目标是将Worker和writer分别指向不同的线程。writer函数会记录workers的工作方式。这不是一个解决方案,只是指出您当前所做的不正确。可能的解决方案是要使
levelOne
成为具有成员函数
worker
的类的实例。您试图将方法用作闭包。在python上,该方法应将函数作为值返回,如:def foo():def bar():pass return bar可能重复的我不认为这是一个解决方案,我不需要返回它的结果。我的目标是分别针对不同线程的工作线程和写入线程。writer函数会记录工作线程的工作方式。这不是一个解决方案,只是指出您当前所做的不正确。a可能的解决方案是使
levelOne
成为具有成员函数
worker
的类的实例。您试图将方法用作闭包。在python上,该方法应将函数作为值返回,如:def foo():def bar():pass return bart这个例子非常适合我的情况。如果可能的话,你能解释一下为什么试图访问问题代码中所示的工作者和作者是糟糕的设计吗?@PeterBejan cf我编辑的答案。我发誓我的示例解决方案不会像你的具体用例(我知道)预期的那样工作