python的数据结构模式匹配与解包
py-pattern-matching的Python项目详细描述
用法
使用两个参数调用patternmatching.match()函数:
- 参数1:要匹配的模式
- 参数2:要匹配的数据结构
- 可选参数flatten: True具有匹配的值 扁平的,即以扁平元组的形式返回,不管其位置如何 在匹配数据的结构中。
返回值:
if flatten is true: match_ok, [matched_value, matched_value, matched_value, ...] if flatten is not true: match_ok, matched_data_structure
警告: 如果忽略模式中的所有匹配值,match()不返回元组,而是返回布尔值。
是的:
match_ok = match(PATTERN, DATA)
否:
match_ok, = match(PATTERN, DATA)
内置匹配对象
- 任何
- 是实例
任何匹配对象都可以用IGNORE()包装以忽略该值 与返回值中的匹配对象匹配。
IGNORE本身可以用作IGNORE(ANY)的快捷方式。
assert True == match(IGNORE, 123)
在(单元)测试中使用(但也在其他任何地方使用)
如果不能比较函数的返回值,则比较起来很繁琐 只需使用=运算符例如,当函数返回 你只关心元组的某些部分而不关心 整个元组:
retval = some_function_under_test() assert retval and isinstance(retval, tuple) \ and len(retval) == 3 and retval[0] == 'foo' \ and isinstance(retval[1], tuple) and len(retval[1]) == 2 \ and isinstance(retval[1][1], SomeException)
使用模式匹配:
retval = some_function_under_test() assert retval == ('foo', (ANY, IS_INSTANCE(SomeException)), ANY)
示例
MATCH OK
match_ok, value = match(ANY, 'foobar') assert match_ok and value == 'foobar' match_ok = match(IGNORE(ANY), 'foobar') assert match_ok match_ok, value1, value2 match((ANY, ANY), ('foo', 'bar')) assert match_ok and value1 == 'foo' and value2 == 'bar' match_ok, (value1, value2) = match((ANY, ANY), ('foo', 'bar'), flatten=False) assert match_ok and value1 == 'foo' and value2 == 'bar' match_ok, (value1, ) = match((ANY, IGNORE(ANY)), ('foo', 'whatev')) assert match_ok and value1 == 'foo' match_ok, value1, value2 = match(('foo', ANY, ANY), ('foo', 1, 2)) assert match_ok and value1 == 1 and value2 == 2 match_ok, value1, value2, value3 = match(('foo', ANY, (ANY, ANY)), ('foo', 1, (2, 3))) assert match_ok and value1 == 1 and value2 == 2 and value3 = 3 match_ok, (value1, (value2, value3)) = match(('foo', ANY, (ANY, ANY)), ('foo', 1, (2, 3)), flatten=False) assert match_ok and value1 == 1 and value2 == 2 and value3 = 3
NO MATCH
match_ok = match(3, 4) assert not match_ok # notice how you can still successfully do unpacking of return values and just ignore `value` if the match failed match_ok, value = match(IS_INSTANCE(unicode), '123132') assert not match_ok # notice how you can still successfully do unpacking of return values and just ignore `value` if the match failed match_ok, (value1, (value2, value3)) = match(('foo', (ANY, (ANY, ANY))), ('not-foo', (1, (2, 3)))) assert not match_ok # ...even when the structure of the data completely mismatches match_ok, (value1, (value2, value3)) = match(('foo', (ANY, (ANY, ANY))), ('foo', 'blabla')) assert not match_ok # ...don't rely on `value1`, `value2` and `value3` being `None` though--the matcher can still return whatever it wants there; you have to check `match_ok` yourself.