使用 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
启动线程;None
是 incr
隐含的 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()
.
传递时为每个线程保持独立的 counter
s
当您键入 function()
时,这些括号告诉 Python 到 运行 该函数在该位置起作用。所以
x = function()
表示在运行时x
会被设置为function
returns的值。但是,如果您省略了方括号,那么您指的不是返回值,而是函数本身。所以
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
) :)
我对 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
启动线程;None
是 incr
隐含的 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()
.
counter
s
当您键入 function()
时,这些括号告诉 Python 到 运行 该函数在该位置起作用。所以
x = function()
表示在运行时x
会被设置为function
returns的值。但是,如果您省略了方括号,那么您指的不是返回值,而是函数本身。所以
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
) :)