所以我正在为Minecraft地形操纵程序MCEdit编写一个过滤器。过滤器是用Python 2编写的(这是MCEdit唯一能读的东西)。 MCEdit通过将变量级别(类型MCLevel),框和选项传递给用户定义的函数perform(级别,框,选项)来调用过滤器。你可以在这里找到关于这个的文件>> https://github.com/mcedit/pymclevel
我以前写过多个过滤器,所以我知道它是如何工作的一般概念。这是我的代码:
from pymclevel import *
import random
inputs = (("Replace", (0, 1, 255)), ("Of Damage", (0, 0, 15)), ("With", (1, 1, 255)), ("Of Damage ", (0, 0, 15)), ("This Percent of the Time", (50, 0, 100)), ("If it is Beside", (False)), ("Or Diagonal", (False)), ("Exclusively", (False)), ("To", (0, 1, 255)), ("Of Damage ", (0, 0, 15)))
def getBlock(x, y, z):
global level
return (level.blockAt(x, y, z), level.blockDataAt(x, y, z))
def setBlock(x, y, z, block, data):
global level
level.setBlockAt(x, y, z, block)
level.setBlockDataAt(x, y, z, data)
def IsBeside(x, y, z, block, data):
return (getBlock(x - 1, y, z) == (block, data) or getBlock(x + 1, y, z) == (block, data) or getBlock(x, y - 1, z) == (block, data) or getBlock(x, y + 1, z) == (block, data) or getBlock(x, y, z - 1) == (block, data) or getBlock(x, y, z + 1) == (block, data))
def IsDiagonal(x, y, z, block, data):
return (getBlock(x - 1, y - 1, z) == (block, data) or getBlock(x - 1, y, z - 1) == (block, data) or getBlock(x, y - 1, z - 1) == (block, data) or getBlock(x + 1, y + 1, z) == (block, data) or getBlock(x + 1, y, z + 1) == (block, data) or getBlock(x, y + 1, z + 1) == (block, data) or getBlock(x + 1, y + 1, z + 1) == (block, data) or getBlock(x - 1, y + 1, z + 1) == (block, data) or getBlock(x + 1, y - 1, z + 1) == (block, data) or getBlock(x + 1, y + 1, z - 1) == (block, data) or getBlock(x - 1, y - 1, z + 1) == (block, data) or getBlock(x - 1, y + 1, z - 1) == (block, data) or getBlock(x + 1, y - 1, z - 1) == (block, data) or getBlock(x - 1, y - 1, z - 1) == (block, data))
def perform(level, box, options):
Replace = options["Replace"]
ReplaceData = options["Of Damage"]
With = options["With"]
WithData = options["Of Damage "]
Percent = options["This Percent of the Time"]
Beside = options["If it is Beside"]
Diagonal = options["Or Diagonal"]
Exclusive = options["Exclusively"]
Check = options["To"]
CheckData = options["Of Damage "]
mark = False
for x in xrange(box.minx, box.maxx + 1):
for z in xrange(box.minz, box.maxz + 1):
for y in xrange(box.miny, box.maxy + 1):
if random.randint(1, 100) <= Percent and getBlock(x, y, z) == (Replace, ReplaceData):
if Beside and not Diagonal and not Exclusive:
if IsBeside(x, y, z, Check, CheckData):
mark = True
elif not Beside and Diagonal and not Exclusive:
if IsDiagonal(x, y, z, Check, CheckData):
mark = True
elif Beside and not Diagonal and Exclusive:
if IsBeside(x, y, z, Check, CheckData) and not IsDiagonal(x, y, z, Check, CheckData):
mark = True
elif not Beside and Diagonal and Exclusive:
if not IsBeside(x, y, z, Check, CheckData) and IsDiagonal(x, y, z, Check, CheckData):
mark = True
elif Beside and Diagonal:
if IsBeside(x, y, z, Check, CheckData) and IsDiagonal(x, y, z, Check, CheckData):
mark = True
else:
mark = True
if mark:
level.setBlock(x, y, z, With, WithData)
mark = False
我的问题是我需要多次调用getBlock和setBlock,并且很可能该级别将包含大量信息(足以将其复制到函数中需要几秒钟)。通过扩展,这意味着过滤器可以轻松运行数小时,大部分时间只用于复制级别。当然,我不想这样做,因为python没有通过引用传递,并且我无法访问传递给执行的原始变量,我只能尝试访问传递给执行的级别的实例其他功能。这就是全球性的东西进入的地方,这显然是行不通的。有没有人知道如何在不将level作为函数参数传递给getBlock和setBlock的情况下完成这项工作?我不在乎它是否使用全局,这只是我的想法。
答案 0 :(得分:1)
您是否运行此代码并确认它实际上非常慢? Python不使用pass-by-value或pass-by-reference,而是使用pass-by-assignment进行参数传递。一开始可能很难掌握,但这样做有一些重要的原因。基于我的理解,将非常大的对象传递给python中的函数并不像C / C ++那样繁琐,因为您不是将对象数据从一个内存位置复制到另一个内存位置,而是复制分配数据。我经常听到它被称为“按值传递参考”,这意味着您正在通过值传递引用。这很令人困惑,我更喜欢这种解释:Code like a pythonista
如果您想更改被调用者中参数的内容或值,并将这些更改反映在外部作用域中,可以采用多种方法。如果参数总是可变的(例如列表),那么你可以在被调用者中修改它们没有任何问题,只要你的修改是就地的,例如没有重新分配。如果它们是不可变的,那么最好的办法就是返回一个已更改对象的元组。您还可以查看传递分配文章中的其他技术(与上面相同的链接)。
希望我没有让你更困惑。祝你好运!
P.S。如果你有时间,请将其余的Code作为pythonista读取。这是一个非常快速的阅读和充满提示,使您的python编码更顺利。