我对Twisted python很感兴趣,正在做我的每周"保持最新和练习"阅读http://jdb.github.io/concurrent/preemptive.html。
摘要: 使用 incr()和 incr 作为参数有什么区别?当我将函数声明为incr()时,我得到"正确"即使有大量的结果。但是,当我宣布它为incr时,我得到错误的结果。谷歌上的快速搜索只是告诉我如何在类中声明函数。
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
答案 0 :(得分:2)
让我告诉你。
让我们定义一些测试功能。哪个会在被解雇时打印出来的东西
>>> 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
):)
答案 1 :(得分:1)
当您键入function()
时,这些括号会告诉Python在该位置运行该函数。所以
x = function()
表示x
将被设置为function
运行时返回的值。但如果省略括号,则不是指返回的值,而是指函数本身。所以
x = function
表示x
现在是函数,可以使用x()
调用。
在您的情况下,传递incr
返回的内容与函数本身之间的区别。
答案 2 :(得分:0)
在您的示例中,target=incr()
将尝试在主线程中运行incr
而不传递参数(即使它成功了,当它尝试使用{启动线程时也不会执行任何操作{1}} None
; target
是None
隐式返回的内容。使用incr
运行将按预期执行线程中的递增。
使用target=incr
的情况是使用闭包来避免污染全局范围。例如,在Python 3中,您可以这样做:
target=incr()
这将创建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
范围内未共享的每个线程counter
;通过设置global
,它会调用外部target=incr()
并将包含的函数incr
作为真实incr_inner
返回,并使用其自己唯一的target
变量。
作为闭包的嵌套主要是关于实现隐藏和简洁(并且它并不总是按照您的希望工作;在Python 2中,没有counter
关键字,它无法运行写得没有一些hackery)。但是你可以在任何Python版本中从一个类中创建nonlocal
个对象,并获得大致相同的“有状态线程”行为。例如:
callable
就像闭包一样,这个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
传递时,每个线程都保持独立的counter
。