我试图弄清楚Python练习中的情况 问题是:
定义两个函数:
限制:
以下代码将描述这种情况:
# >>> p()
# 0
# >>> q()
# >>> q()
# >>> p()
# 2
# >>> print([k for k,v in globals().items() if v==2])
## checks that a variable with the value ‘2’ does not exist in the global environment.
# []
我想得到一些建议,我该如何解决呢 感谢。
答案 0 :(得分:2)
您可以在函数的本地范围内定义变量:
def p():
i = [0]
def p():
return i[0]
def q():
i[0] += 1
return p, q
p, q = p()
print(p())
# 0
q()
q()
print(p())
# 2
print([k for k,v in globals().items() if v==2])
# []
在Python3中,您可以使用nonlocal
语句,这样就可以使i
成为int而不是列表:
def p():
i = 0
def p():
return i
def q():
nonlocal i
i += 1
return p, q
答案 1 :(得分:0)
免责声明:这不是一个非常严肃的答案。符合OP中规定的规格!
def p():
print(p.__dict__.get('smuggled_value',0))
def q():
p.smuggled_value = getattr(p,'smuggled_value',0) + 1
更严肃的回答:如果您允许p
或q
拥有参数,则此问题很简单。否则你需要做一些漂亮的hacky事情,或者使用全局变量。
修改:按要求说明:
在python中,一切都是对象,包括函数。具有__dict__
属性的对象允许使用object.attribute
语法进行属性分配。通常,您只对class
成员执行此类属性赋值,但函数也允许它。因此,我只允许您创建p
和q
。
请注意,您实际上不应该像这样编码。从你的困惑中可以看出,这种编码方式是无法可读。为你的函数提供参数,使它们具有人类可读性。
答案 2 :(得分:0)
这是一个基于闭包的版本,从未向全局范围引入p
和q
以外的任何符号:
@apply
def p():
x = [0]
def p():
print x[0]
return p
def q():
p.func_closure[0].cell_contents[0] += 1
肯定更多的是在“hacky”方面,而不是“认真回答”方面,但另一方面,你的要求也是如此。 ; - )
我还要说严格满足......
的要求是不可能的改变它的唯一方法是调用q()
因为在这个例子中你可以手动执行q
内部的操作。
(或者你可以利用你的解释器的实现细节,声明一个ctypes
指针,甚至在内存级别做更糟糕的黑客......)
答案 3 :(得分:0)
每次调用时,q可以替换p函数:
p = lambda: 0
def q():
global p
value = p() + 1
p = lambda: value
(虽然它并不完全遵循规范 - 实际上没有任何变量增加)
答案 4 :(得分:0)
因为到目前为止还没有人发布过基于类的解决方案:
class _pq(object):
_x = 0
@classmethod
def p(cls):
print cls._x
@classmethod
def q(cls):
cls._x += 1
p = _pq.p
q = _pq.q
del _pq
答案 5 :(得分:0)
知道了,我的最终答案。只将p和q引入命名空间,永远不会更改它们。该变量位于lambda的默认参数中,该lambda仅调用一次,不带参数,并返回函数。我们避免使用__import __。
将operator放入全局命名空间(对于operator.setitem)p, q = (lambda i=[0]:
(lambda: i[0],
lambda: __import__('operator').setitem(i, 0, i[0]+1))
)()
我认为这种解决方案最适合这个问题,例如除了调用q之外,没有办法改变变量,并且它不会在全局命名空间中引入任何不必要的东西。 感觉更像是Javascript而不是Python: - )