2

python like の背後にあるデザインパターンは何ですか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

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これはデザインの王様だと思います。

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

もう少し巧妙な方法で、コンテキストとコマンド ディクショナリを一緒にマージして、シェルのコマンド セットをシェルの言語で変更できるようにすることもできます。

この設計パターンに名前がある場合、その名前は Read-Eval-Print Loop 設計パターンです。ええ、あなたの質問はそれ自体に答えます。

于 2012-09-21T18:46:31.307 に答える