我正在尝试制作一个非常基本的脚本,该脚本利用TkInter根据用户输入绘制线条.用户将使用参数确定绘制的行,通过命令行执行脚本.
可能的命令是:
(# signifies any whole number the user chooses)
P # (selects a pen to draw with)
D (pen down / starts drawing)
N # (moves the pen north # increments)
E # (moves the pen east # increments)
S # (moves the pen south # increments)
W # (moves the pen west # increments)
U (pen up / stops drawing)
例:
Parser.py P 3 D N 4 E 2 S 4 W 2 U
上面的示例将绘制一个高矩形.
我正在尝试为sys.argv创建一个基本解析器,该解析器将遍历所有参数并根据所述参数及其顺序从字典中执行方法.
这是我的代码,它通过sys.argv运行,并根据参数创建一个数组(我将添加错误检查,因此现在假设一个快乐的日子):
class JoshSourceReader(object):
""" responsibe for providing source text for parsing and drawing
Initiates the Draw use-case.
Links to a parser and passes the source text onwards """
def __init__(self):
self.parser = JoshParser()
self.source = []
def go(self):
i = 1
x = len(sys.argv)
while i < x:
if sys.argv[i]=="P":
self.source.append("P " + str(sys.argv[i + 1]))
i += 2
elif sys.argv[i]=="D":
self.source.append("D")
i += 1
elif sys.argv[i]=="N":
self.source.append("N " + str(sys.argv[i + 1]))
i += 2
elif sys.argv[i]=="E":
self.source.append("E " + str(sys.argv[i + 1]))
i += 2
elif sys.argv[i]=="S":
self.source.append("S " + str(sys.argv[i + 1]))
i += 2
elif sys.argv[i]=="W":
self.source.append("W " + str(sys.argv[i + 1]))
i += 2
elif sys.argv[i]=="U":
self.source.append("U")
i += 1
self.parser.parse(self.source)
因此,将从上面的示例生成的数组如下所示:
source=['P 3', 'D', 'N 4', 'E 2', 'S 4', 'W 2', 'U']
所以我的问题是:如何创建一个有效的方法字典,该字典可与上述数组一起使用并基于数组元素逐个执行方法?我什至开始怀疑是否可行,因为某些方法需要传递属性(数字),而有些则不需要.任何人都可以阐明这件事吗?
并且请记住,我是Python的新手.
编辑:我忘记了一条关键信息. N,E,S,W都引用相同的方法,但是每次使用不同的参数.这是方法(尚未绘制):
def drawLine(self, direction, distance):
print("drawing line of length " + str(distance) + " at "
+ str(direction))
因此,如果我使用“ S 3”来调用此方法,我将这样称呼它:
drawer.drawLine(180, 3)
如果我使用“ W 1”来称呼它,我会这样称呼它:
drawer.drawLine(270, 1)
解决方法:
这是一个棘手的问题,最好使用一个不错的解析框架来解决.我通常建议pyparsing这样的事情.但是,这是一个不使用任何外部框架的解决方案.
这有点丑陋,但基本上,它会将输入字符串(例如“ P 1”)解析为一个运算符和一个整数.字典包含要调用的方法,以及要传递给方法的任何其他参数(对于drawLine()情况).
我无需使用类就可以完成此操作,但是只需将self作为第一个参数添加到所有内容中,就可以解决此问题.
def selectPen(pen):
print('called selectPen with pen', pen)
def penDown():
print('called penDown')
def drawLine(direction, length):
print('called drawLine with direction', direction, 'and length', length)
def penUp():
print('called penUp')
def parseSource(source):
tempSource = [op.split(' ') for op in source]
parsedSource = []
for op in tempSource:
parsedOp = []
for i, el in enumerate(op):
if i == 0:
parsedOp.append(el)
else:
try:
parsedOp.append(int(el))
except ValueError:
parsedOp.append(el)
parsedSource.append(tuple(parsedOp))
return parsedSource
def dispatch(parsedSource):
opDict = {'P':(selectPen,), 'D':(penDown,), 'N': (drawLine, 0), 'S':(drawLine, 180),
'E': (drawLine, 90), 'W': (drawLine, 270), 'U': (penUp,)}
for op in parsedSource:
methodName = op[0]
methodToCall = opDict[methodName][0]
args = op[1:]
if len(opDict[methodName])>1:
args = opDict[methodName][1:] + args
methodToCall(*args)
if __name__ == '__main__':
source=['P 3', 'D', 'N 4', 'E 2', 'S 4', 'W 2', 'U']
parsedSource = parseSource(source)
dispatch(parsedSource)