我目前正在通过为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__
方法,如果存在该方法,则调用该方法,并返回返回值(通常为True
或False
)作为该相等性测试的结果。但是,__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来使&
正常工作。
可以支持|
和&
的原因是or
和and
不能用钩子覆盖(这些短路,一个钩子将需要对两个操作数进行评估,以打破短路期望)。
关于python - 带有属性的怪异python列表语法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18085457/