将一行 Python 代码分成几个部分

Divide a line of Python code into its parts

一些快速上下文,我使用 Vim 文本编辑器和一个名为 UltiSnips 的插件。我的代码中有时会有这样的行,其中我有一本字典,在一行中使用多个键。

someDict["something"]["anotherThing"]

如果此行出现 KeyError,我 select 该行并使用 UltiSnips 插件将其转换成它的部分。

print(someDict)
print(someDict["something"])
print(someDict["something"]["anotherThing"])

它适用于简单的用途,但我希望它更智能一些,因为目前我无法处理任何更复杂的东西,比如这样

someDict["something"][some_module.someOtherDict["somethingElse"]]

(预期输出)

print(someDict)
print(someDict["something"])
print(some_module)
print(some_module.someOtherDict)
print(some_module.someOtherDict["somethingElse"])
print(someDict["something"][some_module.someOtherDict["somethingElse"]])

我正在考虑从我当前的系统(只是捕获 [] 的正则表达式)切换到使用 Python 的 ast 模块处理该行,但事实证明它比我更复杂认为是因为 ast 从我预期的方式向后评估。我写信是想询问是否已经存在类似的东西,或者是否有更好的方法来解决这个问题。

用于测试解决方案的示例集(输入顶行,打印行是预期输出):

something
print(something)

something.anotherThing
print(something)
print(something.anotherThing)

something.anotherThing()
print(something)
print(something.anotherThing)
print(something.anotherThing())

something.anotherThing()['aDictKey'].moreMethods(valueInfo, 8, 'methodString', someKeyword=value, *args, **kwargs)
print(something)
print(something.anotherThing)
print(something.anotherThing())
print('aDictKey')
print(something.anotherThing()['aDictKey'])
print(something.anotherThing()['aDictKey'].moreMethods)
print(valueInfo)
print(8)
print('methodStrings')
print(value)
print(*args)
print(**kwargs)
print(valueInfo, 8, 'methodString', someKeyword=value, *args, **kwargs)
print(something.anotherThing()['aDictKey'].moreMethods(valueInfo, 8, 'methodString', someKeyword=value, *args, **kwargs))

something.anotherThing()[(someObj.someDict['itsKey'], 8, True)].moreMethods()
print(something)
print(something.anotherThing)
print(something.anotherThing())
print(someObj)
print(someObj.someDict)
print('itsKey')
print(someObj.someDict['itsKey'])
print(8)
print(True)
print(something.anotherThing()[someObj.someDict['itsKey']])
print(something.anotherThing()[someObj.someDict['itsKey']].moreMethods)
print(something.anotherThing()[someObj.someDict['itsKey']].moreMethods())

当我有更多时间处理这个问题时,我会post我自己的解决方案

这是一个使用 ASTTokens 的解决方案:

import ast, asttokens

def expand(line):
  atok = asttokens.ASTTokens(line, parse=True)
  return [atok.get_text(n) for n in ast.walk(atok.tree)
          if isinstance(n, ast.expr) and not isinstance(n, (ast.Num, ast.Str))]

for expr in reversed(expand('someDict["something"][some_module.someOtherDict["somethingElse"]]')):
  print("print(%s)" % expr)

输出:

print(some_module)
print(some_module.someOtherDict)
print(some_module.someOtherDict["somethingElse"])
print(someDict)
print(someDict["something"])
print(someDict["something"][some_module.someOtherDict["somethingElse"]])