c++ - 像交互式 shell 一样设计 python

标签 c++ design-patterns

interactive shell这样的python背后的设计模式是什么。我想为我的服务器执行此操作,但我最终得到了很多 if - then- else 模式。

例如,当我启动 python interpreter 时,我得到这样的结果

Python 2.6.7 (r267:88850, Feb  2 2012, 23:50:20)
[GCC 4.5.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> help

help后提示改成help

Welcome to Python 2.6!  This is the online help utility.

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".

help>

我认为这是read-eval loop设计之王。

最佳答案

对于 REPL,您需要一个上下文(一个存储 REPL 状态的对象)、一个命令解析器(它解析输入并生成 AST)以及一种将命令映射到操作的方法(操作通常只是修改的函数上下文和/或产生副作用)。

一个简单的 REPL 可以像下面这样实现,其中上下文是使用一个简单的字典实现的,AST 只是输入的命令在空格上分割,字典用于将命令映射到操作:

context = {}
commands = {}

def register(func):
    """ convenience function to put `func` into commands map """
    # in C++, you cannot introspect the function's name so you would
    # need to map the function name to function pointers manually
    commands[func.__name__] = func
def parse(s):
    """ given a command string `s` produce an AST """
    # the simplest parser is just splitting the input string,
    # but you can also produce use a more complicated grammer
    # to produce a more complicated syntax tree
    return s.split()
def do(cmd, commands, context):
    """ evaluate the AST, producing an output and/or side effect """
    # here, we simply use the first item in the list to choose which function to call
    # in more complicated ASTs, the type of the root node can be used to pick actions
    return commands[cmd[0]](context, cmd)

@register
def assign(ctx, args):
    ctx[args[1]] = args[2]
    return '%s = %s' % (args[1], args[2])
@register
def printvar(ctx, args):
    print ctx[args[1]]
    return None
@register
def defun(ctx, args):
    body = ' '.join(args[2:])
    ctx[args[1]] = compile(body, '', 'exec')
    return 'def %s(): %s' % (args[1], body)
@register
def call(ctx, args):
    exec ctx[args[1]] in ctx
    return None
# more commands here

context['PS1'] = "> "
while True:
    # READ
    inp = raw_input(context["PS1"])

    # EVAL
    cmd = parse(inp)
    out = do(cmd, commands, context)

    # PRINT
    if out is not None: print out

    # LOOP

示例 session :

> assign d hello
d = hello
> printvar d
hello
> assign PS1 $
PS1 = $
$defun fun print d + 'world'
def fun(): print d + 'world'
$call fun
helloworld

再多一点技巧,您甚至可以将上下文和命令字典合并在一起,从而允许用 shell 的语言修改 shell 的命令集。

这个设计模式的名字,如果有名字的话,就是Read-Eval-Print Loop设计模式;是的,您的问题可以自行解答。

关于c++ - 像交互式 shell 一样设计 python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12535365/

相关文章:

.net - 没有行为的 Entity Framework POCO-需要重新设计以消除代码异味

java - 在 Tic Tac Toe 中表示游戏状态

c++ - 无法让简单的 ifstream 在 Visual Studio Express 中工作

c++ - 如何定义 bool 运算符来比较类的精确属性?

c# - 尝试应用良好的依赖注入(inject)实践时遇到的问题

java - 我想为搜索类实现一个接口(interface),实现接口(interface)的最佳方法是什么?

C++:转储 RAM 内容

c++ - 从 vector 中调用派生类函数 (c++)

c++ - 使用在不同修订版共享相同代码的 C++ 项目的 Git 方法是什么?

design-patterns - 结构与行为设计模式