文章来自《Python cookbook》.

翻译仅仅是为了个人学习,其它商业版权纠纷与此无关!

-- 0.706 [2004-09-28 19:54:12]

1. Dispatching Based on Pattern Matches 基于模式匹配的调度

Credit: Michael Robin

1.1. 问题 Problem

You need to use regular expressions to match strings and then automatically call functions with arguments based on the matched strings.

你需要使用规则表达式去匹配字符串,然后根据匹配的字符串生成参数并自动地调用相应的函数。

1.2. 解决 Solution

Once again, a class offers a good way to package together some state and some behavior:

再一次,把一些状态和一些行为用一个类包装起来,是一个好方法:

   1 import re
   2 
   3 class Dispatcher:
   4 
   5     def _dispatch(self, cmdList, str):
   6         """ Find a match for str in the cmdList and call the associated
   7            method with arguments that are the matching grouped subexpressions
   8            from the regex.
   9         """
  10         for comment, pattern, command in cmdList:
  11              found = pattern.match(str)   # or, use .search(  )
  12              if found: return command(self, *found.groups(  ))
  13 
  14     def runCommand(self, cmd):
  15         self._dispatch(Commands, cmd)
  16 
  17     # example methods
  18 
  19     def cmd1(self, num, name):
  20         print "The number for %s is %d" % (name, int(num))
  21         return 42
  22 
  23     def cmd2(self, partnum):
  24         print "Widget serial #: %d" % int(partnum)
  25 
  26 Commands = [
  27       [ 'Number-to-name correspondence',
  28               r'X (?P<num>\d),(?P<name>.*)$',
  29               Dispatcher.cmd1],
  30       [ 'Extract Widget part-number',
  31               r'Widget (?P<partnum>.*)$',
  32               Dispatcher.cmd2],
  33 ]
  34 
  35 # Prepare the Commands list for execution by compiling each re for cmd in Commands:
  36 for cmd in Commands:  #本行为译者加上的,同时修改了下面几行的缩进
  37   try:
  38      cmd[1] = re.compile( cmd[1] )
  39   except:
  40      print "Bad pattern for %s: %s" % ( cmd[0], cmd[1] )

1.3. 讨论 Discussion

In Python, it's generally best to compile regular expressions into re objects.The re module does some caching of string-form regular expressions that you use directly, but it's still better to make sure that regular expressions are not needlessly recompiled.The string form is still available as r.pattern for any compiled re object r, anyway, should you need it (e.g., for debugging/logging purposes).

在Python中,把规则表达式编译进re对象内,通常是最好的。re模块对你直接使用的字符串形式的规则表达式会作一些缓冲,但是确保规则表达式不必重新编译,仍然是比较好的作法。对任何已编译的re对象物体r,无论如何,当需要时,字符串形式仍然可用作 r.pattern(举例来说,为Debug/log目的)。

You can use regular expressions to match strings (or search into strings) and automatically call appropriate functions, passing as arguments substrings of the matched string that correspond to the groups of the regular expression.

你能使用规则表达式去匹配(match)字符串(或在其中搜索(search)) ,而且自动地调用适当的函数,并把与规则表达式中的组相匹配的子串作为参数传递给它。

This recipe exemplifies one approach to this solution. The idea is that: 这一配方是这一解决方案的例子。它的主意是:

   1 r = self.runCommand("X 36,Mike")

automatically calls:

自动地调用:

   1 cmd1(self, "36", "Mike")

and binds the variable r to 42, the result of cmd1.

而且把cmd1 的结果42,绑定到变量 r。

This specific example might be best approached with direct string manipulation (testing str[0], then using the split method of strings), but regular expressions let you handle much more complicated cases with nearly equal ease.

在这个特定的例子里,可能最好的方案是直接处理字符串(测试str[0],然后使用字符串的split方法),但是规则表达式可以让你用几乎同样简单的方式处理复杂得多的情形。

An idiomatic Pythonic approach is to put each pattern to be compiled directly in the structure to be created at load-time. For example:

惯用的Pythonic方式是在调用时,直接在结构中将每个模式编译。举例来说:

   1 Cmds = ( (re.compile(r"^pa(t)t1$"), fn), ... )

This is simple, if you don't require any special processing, but I think it's a little prettier to avoid including code in data-structure initializers.

如果你不需要任何的特别处理,这很简单。但是我认为避免在数据结构的初始化中包含代码,要稍微漂亮一些。

1.4. 参考 See Also

Documentation for the re module and regular-expression objects in the Library Reference.