2

我目前正在通过为 MCedit python 程序编写过滤器来学习 python,MCedit python 程序是 Minecraft 的 3D 块编辑器。过滤器是可以作为函数在程序内部运行的小段代码。

MCedit 提供的功能之一允许提取原理图(此处命名为 temp)以对其进行修改。在演示中,程序的创建者修改原理图的块属性,通过以下行:

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

.blocks 属性由 3 层 (x, y, z) 上的串联列表组成。

这段代码将任何列表中等于 14 的任何值替换为 52。

我试图让它改变其他值,用:

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

但它根本行不通。

我知道还有其他方法可以做到这一点,但是这个特别简单、紧凑和高效,我想了解它是如何工作的。

4

1 回答 1

2

底层blocks类的作者已经替换了各种 Python 表达式的正常语义来实现一个迷你查询语言。

最有可能的是,blocks该类覆盖了__setitem__and__eq__钩子。

temp.blocks == 14表达式由钩子处理并__eq__返回某种专门的对象,然后通过语法传递给__setitem__钩子。[...]然后,该__setitem__钩子使用该专门对象来确定要更改序列中的哪些索引。

运算符在任一操作数上==查找__eq__方法,如果存在,则调用该方法并返回返回值(通常为TrueFalse)作为该相等性测试的结果。但是,__eq__方法 ontemp.blocks返回别的东西;并且“某事”还可以实现额外的钩子(例如__or____and__),以使对查询语言的进一步改进成为可能。

temp.blocks[expr1] = expr2分配被转换为,因此的blocks.__setitem__(expr1, expr2)结果blocks.__eq__(14)被传递给该方法,以便它根据“搜索查询”更改基础序列。

猜测一下,如果特殊对象实现了钩子,temp.blocks[temp.blocks == 14 | temp.blocks == 15] = 52 可以工作;它也可以实现钩子以使其正常工作。__or____and__&

可以支持的原因是并且不能|用钩子覆盖(这些短路,钩子将需要评估两个操作数以打破短路预期)。&orand

于 2013-08-06T16:22:45.683 回答