2

python 背后的设计模式是什么interactive shell。我想为我的服务器做这个,但我最终得到了很多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

帮助后提示更改为帮助

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设计之王。

4

1 回答 1

1

对于 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

一个示例会话:

> 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设计模式;所以,是的,你的问题可以自己回答。

于 2012-09-21T18:46:31.307 回答