使用 Python 函数作为 class

Using Python functions as class

我对 Twisted python 很感兴趣并且每周 "keep-up-to-date-and-practice" 阅读 http://jdb.github.io/concurrent/preemptive.html

总结: 使用 incr()incr 作为参数有什么区别?当我将函数声明为 incr() 时,即使数字很大,我也会得到 "correct" 结果。但是,当我将其声明为 incr 时,我得到了错误的结果。对 google 的快速搜索告诉我如何在 类.

中声明函数
Thread(target=incr, args=(i,))

Thread(target=incr(), args=(i,))

其中 incr 是:

counter = 0

def incr(num):
    global counter
    count = 0
    for i in range(1000):
        counter += 1
        print "\nWorker: {}, Counter: {}, Self-count: {} .".format(num, counter, count)

    print counter

在您的示例中,target=incr() 会在主线程中尝试 运行 incr 而没有传递参数时死掉(即使它成功了,它在尝试时也不会执行任何操作以 None 作为 target 启动线程;Noneincr 隐含的 returns)。 运行 target=incr 将按预期在线程中执行递增。

使用 target=incr() 的情况是使用闭包来避免污染全局范围。例如,在 Python 3 中,您可以这样做:

def incr():
    counter = 0

    def incr_inner(num):
        nonlocal counter
        count = 0
        for i in range(1000):
            counter += 1
            print("\nWorker: {}, Counter: {}, Self-count: {} .".format(num, counter, count))

        print(counter)
    return incr_inner

这将创建一个未在 global 范围内共享的每线程 counter;通过设置target=incr(),它会调用外部incr和return封闭的函数incr_inner作为真正的target,有自己独特的counter变量。

作为闭包的嵌套主要是关于实现隐藏和简洁(它并不总是像你希望的那样工作;在 Python 2 中,没有 nonlocal 关键字,它可以' 被写成 运行,没有一些 hackery)。但是您可以在 Python 的任何版本中从 class 创建 callable 对象,并获得大致相同的 "stateful thread" 行为。例如:

class incr(object):
    def __init__(self):
        self.counter = 0

    def __call__(self, num):
        count = 0
        for i in range(1000):
            self.counter += 1
            print("\nWorker: {}, Counter: {}, Self-count: {} .".format(num, self.counter, count))

        print(self.counter)

就像闭包的情况一样,这个 class 可以用作一个参数,在作为 target=incr().

传递时为每个线程保持独立的 counters

当您键入 function() 时,这些括号告诉 Python 到 运行 该函数在该位置起作用。所以

x = function()

表示在运行时x会被设置为functionreturns的值。但是,如果您省略了方括号,那么您指的不是返回值,而是函数本身。所以

x = function

意味着 x 现在是函数,可以用 x() 调用。

在你的情况下,这是传递 incr returns 和函数本身之间的区别。

让我告诉你。

让我们定义一些测试函数。当它被解雇时会打印一些东西

>>> def test():
...     print "fired!"
... 

现在让我们尝试定义线程。

>>> Thread(target=test)
<Thread(Thread-1, initial)>
>>> Thread(target=test())
fired!
<Thread(Thread-2, initial)>

你能看到吗?当您编写 test() 函数时,它会在您启动线程之前被触发。但是如果我们尝试 运行 这个线程会发生什么?

>>> thread1.start()
fired!

>>> thread2.start()
>>> 

没有。那是因为当你写 Thread(target=test) 时,你传递了一个测试函数的实例作为参数。当您编写 Thread(target=test()) 时,您传递了 test() 函数执行的结果 (None) :)