2017-08-08 48 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