【问题标题】:Weird python list syntax with an attribute带有属性的奇怪 python 列表语法
【发布时间】:2013-08-06 16:21:37
【问题描述】:

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

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

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

.blocks 属性由连接列表组成,位于 3 层(x、y、z)上。

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

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

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

但它根本不起作用。

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

【问题讨论】:

  • 这看起来很像 NumPy。 temp.blocks 实际上是由嵌套列表组成的,还是 NumPy ndarray?
  • @user2357112:我确实在编辑器源代码中看到了numpy 依赖项。

标签: python list syntax minecraft


【解决方案1】:

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

blocks 类很可能会覆盖 __setitem____eq__ 挂钩。

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

== 运算符在任一操作数上查找__eq__ 方法,如果存在,则调用该方法并返回返回值(通常为TrueFalse)作为该相等性测试的结果.然而,temp.blocks 上的 __eq__ 方法返回了一些东西 else;并且“某事”还可以实现额外的钩子(例如__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 不能被钩子覆盖(这些短路,钩子需要评估两个操作数中断 em> 短路预期)。

【讨论】:

  • 详细说明,or 在 Python 中是不可覆盖的(and 也不是),因为它会短路,因此实际上可能不需要评估第二个参数;但是,调用方法需要在调用之前评估两个参数。有人提议改变它(PEP 335),但被拒绝了。这就是为什么您可能需要使用算术或 | 来代替。
  • @kindall:是的,在答案中详细说明了这一点。
  • 非常感谢您的帮助,我想我理解了大部分内容,很遗憾这不是我以前从未听过的某种秘密列表语法。然而,两者 |而&返回一个ValueError,说我应该使用a.all()或者a.any(),所以我猜他没有实现多语句兼容。
  • @user2657597:那么您很可能拥有numpy.ndarray 对象。见numpy.org
  • 我在 temp.blocks 上使用了 type (),它确实返回了 numpy.ndarray,但是,文档没有提到这种列表构建。
猜你喜欢
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多