在javascript中我可以用这样的闭包写函数
function getUniqueIDfunction() {
var id = 0;
return function() { return id++; };
};
然后使用它
uniqueID = getUniqueIDfunction();
uniqueID(); //return 0
uniqueID(); //return 1
...
我可以在Python中执行相同的操作(如果它取决于不同的版本,请告诉我)?
def getUniqueIDfunction():
x = -1
def foo():
#And I know that it doesn't work with row bellow and without it
#global x
x += 1
return x
return foo
这只是一个样本。我想知道Python中的闭包。
答案 0 :(得分:5)
Python 3使用PEP 3104和nonlocal
语句引入了这种范围行为:
>>> def uniqueId ():
x = -1
def inner ():
nonlocal x
x += 1
return x
return inner
>>> f = uniqueId()
>>> f()
0
>>> f()
1
>>> f()
2
除此之外,在以前的版本中,闭包确实存在,但您只有只读访问权限。因此,更改x
将无效。但是你可以做的是使用一个可变对象,比如一个列表,并改变它:
>>> def uniqueId ():
x = [-1]
def inner ():
x[0] += 1
return x[0]
return inner
>>> f = uniqueId()
>>> f()
0
>>> f()
1
由于您可以使任何类型的对象可调用,您还可以通过定义具有__call__
方法的自己的类型来做更多花哨的事情:
>>> class UniqueId:
def __init__ (self):
self.x = -1
def __call__ (self):
self.x += 1
return self.x
>>> f = UniqueId()
>>> f()
0
>>> f()
1
答案 1 :(得分:3)
如果你想要的只是一个唯一的ID,只需使用以下内容:
def uniqueID():
x = 0
while True:
yield x
x += 1
id = next(uniqueID)
如果您愿意,可以使用闭包(poke mentions in his answer)重写此内容:
def getUniqueIDfunction():
x = -1
def uniqueID():
nonlocal x
x += 1
return x
return uniqueID
uniqueID = getUniqueIDfunction()
id = uniqueID()
这有一点需要注意,它只适用于Python 3+。对于Python 2,您可以通过将值x
附加到类来模拟此行为。
答案 2 :(得分:2)
这样可行,但并不能完全符合您的要求:
def getUniqueIDfunction():
x = -1
def foo(x=x):
x += 1
return x
return foo
f() # returns 0
f() # returns 0 again!
因为整数数据类型是不可变的。相反,如果您使用可变数据类型:
def counter():
x = [0]
def enc():
x[0] = x[0] + 1
return x[0]
return enc
f = counter()
f() # returns 1
f() # returns 2
f() # returns 3
另一个更复杂的例子来自我自己的用法:
def enumerate_dupes_in_column():
'''
provides a dict for counting in the namespace and a function for the
operation, thus avoiding global variable naming
'''
countdict = {}
def countfunction(arg):
countdict[arg] = countdict.get(arg, 0) + 1
if countdict[arg] == 1:
return arg
else:
return arg + ', ' + str(countdict[arg])
return countfunction
f = enumerate_dupes_in_column()
f('foo') # returns foo
f('bar') # returns bar
f('foo') # returns foo, 2
答案 3 :(得分:1)