我正在为游戏制作幻想编程语言,所以我正在用python编写语言和解释器。该语言就像命令流一样,每个“步骤”都被解释。输入一串代码,并将其转换为命令对象列表。解释器处理命令,但是某些命令需要能够访问解释器的属性。
例如,解释器跟踪活动命令(从第一个命令编号),因此goto命令将需要更改活动命令。我目前的做法是将数据传递到命令中,对其进行修改,然后解释器将其属性设置为与之相等。
self.current = active.evaluate(self.current)
这将当前命令号设置为等于使用输入的当前命令号评估的活动命令。这是整个块的外观:
if active.complete(): # on command completion
type = active.return_type # get return type
# passes in requested data to modify
if type == "var": # changing var stream
self.var = active.evaluate(self.var)
elif type == "stream": # changing packet stream
self.stream = active.evaluate(self.stream)
elif type == "current": # changing current packet
self.current = active.evaluate(self.current)
elif type == "value": # returns argument for next command
self.holder = active.evaluate(self.var)
self.resolve = True
elif type == "none":
active.evaluate()
这似乎是一种不方便的处理方式,是否有更好的方法从类内部修改类属性?
答案 0 :(得分:1)
我的简单答案是简单地传入解释器本身,然后让对象更改解释器上的相关属性。如果不想过多破坏已有的格式,可以为from csv import writer
# open both input and output csv
with open("addresses.csv") as csv_in, open("output.csv", "w", newline="") as csv_out:
csv_writer = writer(csv_out)
# Skip 'Address' header
next(csv_in)
# Write new headers
csv_writer.writerow(["First Address", "Last Address"])
# Go through each line in csv
for line in csv_in:
# Split ranges from rest of line
ranges, *rest = line.split()
# Split ranges themselves
start, end = ranges.split("-")
# Get difference between length of numbers
diff = len(start) - len(end)
# Create new end address
end = start[:diff] + end
# Write new lines to output csv
csv_writer.writerow([" ".join([start, *rest]), " ".join([end, *rest])])
函数提供两个参数:
evaluate()
然后您会这样称呼
def evaluate(interpreter, field_name):
interpreter.setattr(field_name, some_value)
但是,这似乎是实现多态性的好地方,它可以解决您所要解决的问题,并消除了对active.evaluate(self, "var")
语句不断增长的需求。
首先,假设您有一个命令超类:
if
当前,似乎您正在使用命令的class Command:
def complete():
# do something, return a boolean
def evaluate(interpreter):
raise NotImplementedException()
来更改对命令的操作。但是,为什么不简单地检测将要运行的命令类型,并相应地实例化具有不同行为的另一个子类呢?
return_type
之后,您只需在解释器中调用class GotoCommand(Command):
def evaluate(interpreter):
interpreter.current = some_value
class PacketCommand(Command):
def evaluate(interpreter):
interpreter.stream = some_other_value
...
,甚至不必关心它是哪种命令。