2017-08-08 47 views
0

我只是把我的手放在SHA2017徽章上。我写了下面的程序,并在模拟器中运行它:这是一个MicroPython的bug吗?

import ugfx 
import badge 

def key_pressed(key, is_pressed): 
    print('key_pressed(key=%r, is_pressed=%r)' % (key, is_pressed)) 

badge.init() 
ugfx.init() 
ugfx.input_init() 
for key in [ugfx.JOY_LEFT, ugfx.JOY_UP, ugfx.JOY_RIGHT, ugfx.JOY_DOWN]: 
    ugfx.input_attach(key, (lambda is_pressed: key_pressed(key, is_pressed))) 
# Uncommenting this makes all keystrokes get interpreted as JOY_UP: 
# ugfx.input_attach(key, (lambda is_pressed: key_pressed(key, is_pressed))) 
# But uncommenting this makes JOY_UP work as intended and doesn't affect other keys 
# ugfx.input_attach(ugfx.JOY_UP, (lambda is_pressed: key_pressed(ugfx.JOY_UP, is_pressed))) 
while True: 
    pass 

如果我运行此,按任意键会说,我按下JOY_DOWN。取消第一行的注释将使所有人都说我按下了JOY_UP,只有取消注释最后一个注释行才会使所有的按键触发JOY_DOWN,除了按预期工作的JOY_UP。

这是错误还是预期行为?似乎MicroPython只编译一次lambda,并将引用关联到“key”,这对我来说似乎很奇怪。

+0

注释行显示为相同。 – user2357112

+0

@ user2357112你是对的,我只是改变了它 – d33tah

+0

与许多其他语言不同,Python中的lambda不构成闭包;它仍然是指外部变量,而不是本地副本。 – 9000

回答

1

的问题是变量key被更新,因而在拉姆达的所有引用表达式被更新,以及:

您需要范围key还有:

for key in [ugfx.JOY_LEFT, ugfx.JOY_UP, ugfx.JOY_RIGHT, ugfx.JOY_DOWN]: 
    ugfx.input_attach(key,lambda k: (lambda is_pressed: key_pressed(k, is_pressed)(key)))

或者你可以使用:

from functools import partial 

for key in [ugfx.JOY_LEFT, ugfx.JOY_UP, ugfx.JOY_RIGHT, ugfx.JOY_DOWN]: 
    ugfx.input_attach(key,partial(lambda k, is_pressed: key_pressed(k, is_pressed),key))

或者使用默认值:

from functools import partial 

for key in [ugfx.JOY_LEFT, ugfx.JOY_UP, ugfx.JOY_RIGHT, ugfx.JOY_DOWN]: 
    ugfx.input_attach(key,lambda is_pressed, k=key: key_pressed(k, is_pressed)))
+0

这太难看了!谢谢:D – d33tah

+0

@ d33tah:我同意这一点。你也可以定义一个函数,然后返回一个lambda表达式等,但它仍然不是很优雅。 –

+0

'functools.partial'会更清晰。 – user2357112