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

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

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


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

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

我试图使它更改其他值,方法是:

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


但这根本行不通。

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

最佳答案

底层blocks类的作者已替换了各种Python表达式的常规语义,以实现一种小型查询语言。

blocks类很可能覆盖__setitem____eq__挂钩。

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

==运算符在任一操作数上查找__eq__方法,如果存在该方法,则调用该方法,并返回返回值(通常为TrueFalse)作为该相等性测试的结果。但是,__eq__上的temp.blocks方法会返回其他内容。并且“某物”还可以实现附加的钩子(例如__or____and__),从而可以进一步优化查询语言。

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

猜测,只要特殊对象实现temp.blocks[temp.blocks == 14 | temp.blocks == 15] = 52 hook__or__也可以工作。它也可以实现__and__ hook来使&正常工作。

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

关于python - 带有属性的怪异python列表语法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18085457/

10-11 03:48