2013-08-06 60 views
2

我目前正在通過爲MCedit python程序編寫過濾器來學習python,這是一個Minecraft的3D塊編輯器。 過濾器是一小段代碼,可以作爲一個函數在程序中運行。具有屬性的奇怪的Python列表語法

MCedit給出的函數之一允許提取一個原理圖(這裏命名爲temp)來修改它。在演示中,該程序的創造者修改示意性的塊屬性,通過下面的行:

temp.blocks[temp.blocks == 14] = 52 

的.blocks屬性是由級聯列表,對3層(X,Y,Z)。

這一段代碼由52

我試圖使它改變其他值,其中替換任何在任何名單等於14的值的:

temp.blocks[temp.blocks == 14 or temp.blocks == 15] = 52 

但它只是不起作用。

我知道還有其他方法可以做到這一點,但是這個方法非常簡單,緊湊和高效,我想了解它是如何工作的。

+0

這看起來很像NumPy。 'temp.blocks'實際上是由嵌套列表組成的,還是NumPy ndarray? – user2357112

+0

@ user2357112:我在編輯器源代碼中看到'numpy'依賴關係。 –

回答

2

基礎blocks類的作者已經替換了各種Python表達式的正常語義來實現迷你查詢語言。

最有可能的是,blocks類覆蓋了__setitem____eq__掛鉤。

temp.blocks == 14表達由__eq__鉤處理,並返回一些一種專​​門對象的,其隨後經由[...]語法傳遞給__setitem__鉤。然後__setitem__鉤子使用該專用對象來確定要改變序列中的哪些索引。

==操作者會查找一個操作數一__eq__方法,和如果存在的話,該方法被調用和返回值(通常TrueFalse)被返回作爲結果爲相等測試。然而,temp.blocks上的__eq__方法返回其他;並且'某些'也可以實現額外的鉤子(如__or____and__),以進一步優化查詢語言。

temp.blocks[expr1] = expr2作業被轉換爲blocks.__setitem__(expr1, expr2),因此blocks.__eq__(14)的結果被傳遞給該方法,以便根據「搜索查詢」更改基礎序列。

推測,temp.blocks[temp.blocks == 14 | temp.blocks == 15] = 52可能也工作,只要特殊對象實現__or__ hook;它可能會執行__and__ hook以使&也起作用。

原因|&可以支持是orand是不可重寫具有鉤(這些短路,鉤將需要兩個操作數進行評估短路期望)。

+0

詳細說明,'or'在Python中是不可覆蓋的(既不是'和'),因爲它會短路,所以第二個參數實際上可能不需要進行評估;然而,調用方法將需要在調用之前評估兩個參數。有人建議改變([PEP 335](http://www.python.org/dev/peps/pep-0335/#rejection-notice)),但它被拒絕了。這就是爲什麼你可能需要使用算術或者'''來代替。 – kindall

+0

@ kindall:是的,在回答中詳細說明了這一點。 –

+0

非常感謝您的幫助,我想我最瞭解它,可悲的是這不是某種我從未聽過的祕密列表語法。但是,這兩個|並返回一個ValueError,說我應該使用a.all()或a.any(),所以我猜他沒有實現多個語句的兼容性。 – user2657597