如何提取python文件中行的精确缩进?

如何提取python文件中行的精确缩进?,python,indentation,Python,Indentation,我的目标是确定python文件中代码行的精确缩进。由于我将在某个位置插入语句,因此确定一行所需的缩进对于实现我的目标非常重要。该问题可在以下示例中解释: First Scenario #A.py a=0 <----------- indentation '0' spaces or '0' \t while a<5: <----------- indentation '0' spaces or '0' \t prin

我的目标是确定python文件中代码行的精确缩进。由于我将在某个位置插入语句,因此确定一行所需的缩进对于实现我的目标非常重要。该问题可在以下示例中解释:

First Scenario
#A.py

a=0                  <----------- indentation '0' spaces or '0' \t
while a<5:           <----------- indentation '0' spaces or '0' \t
    print a          <----------- indentation '4' spaces or '1' \t
    a=a+1            <----------- indentation '4' spaces or '1' \t

Second scenario
#A.py

a=0                  <----------- indentation '0' spaces or '0' \t
while a<5:           <----------- indentation '0' spaces or '0' \t
        print a      <----------- indentation '8' spaces or '2' \t
        a=a+1        <----------- indentation '8' spaces or '2' \t
第一个场景
#A.py
a=0

line = '    \t  asdf'
len(re.split('\w', line)[0].replace('\t', '    '))
>>> 10
请注意,其他建议的解决方案都不会正确计算制表符。

如何

line = '    \t  asdf'
len(re.split('\w', line)[0].replace('\t', '    '))
>>> 10
请注意,其他建议的解决方案都不会正确计算制表符。

您可以使用正则表达式:

import re
with open("/path/to/file") as file:
    for mark, line in enumerate(file.readlines()):
        print mark, len(re.findall("^ *", line)[0])
第一个数字是行号,第二个是缩进

或者,如果需要特定行,请执行以下操作:

import re
with open("/path/to/file") as file:
    print len(re.findall("^ *", file.readlines()[3])[0])
这将返回第4行的缩进(记住索引将是您想要的行号-1)。

您可以使用正则表达式:

import re
with open("/path/to/file") as file:
    for mark, line in enumerate(file.readlines()):
        print mark, len(re.findall("^ *", line)[0])
第一个数字是行号,第二个是缩进

或者,如果需要特定行,请执行以下操作:

import re
with open("/path/to/file") as file:
    print len(re.findall("^ *", file.readlines()[3])[0])
这将返回第4行的缩进(记住,索引将是您想要的行号-1)。

方法“我对其他技术的了解最少”

“我对其他技术知之甚少”的方法

从“”:

Python不关心如何缩进(可以使用空格或空格) 制表符),或缩进量(可以使用任意数量的空格或 选项卡)。事实上,一个嵌套块的缩进可以完全忽略 与另一个不同。语法规则仅适用于 给定单个嵌套块,其所有语句都必须缩进 右边的距离相同。如果不是这样,你会得到一个 语法错误

这意味着,根据我的理解,如果左边的空白字符(字符串或制表符)序列相同,那么两行具有相同的缩进级别

如果您查看文本编辑器,这可能会使事情变得混乱,因为根据制表位的不同,制表符以不同的宽度呈现,因此看起来相同的内容实际上可能并不相同。从这个意义上讲,即使是缩进到右侧相同距离的
的概念也是有问题的,因为从视觉上讲,“距离”取决于每个编辑器渲染给定空白字符时使用的约定。

来自“”:

Python不关心如何缩进(可以使用空格或空格) 制表符),或缩进量(可以使用任意数量的空格或 选项卡)。事实上,一个嵌套块的缩进可以完全忽略 与另一个不同。语法规则仅适用于 给定单个嵌套块,其所有语句都必须缩进 右边的距离相同。如果不是这样,你会得到一个 语法错误

这意味着,根据我的理解,如果左边的空白字符(字符串或制表符)序列相同,那么两行具有相同的缩进级别


如果您查看文本编辑器,这可能会使事情变得混乱,因为根据制表位的不同,制表符以不同的宽度呈现,因此看起来相同的内容实际上可能并不相同。从这个意义上讲,即使是将相同距离缩进右侧的
概念也是有问题的,因为“距离”,从视觉上讲,将取决于每个编辑器用于呈现给定空白字符的约定。

请注意,您选择的确定缩进的方法可能会对性能产生重大影响。例如,虽然您可以使用正则表达式来测量前导空格,但有更简单、更有效的方法

import re

line = '            Then the result is even.'
r = re.compile(r"^ *")

%timeit len(line) - len(line.lstrip())    # 1000000 loops, best of 3: 0.387 µs per loop
%timeit len(re.findall(r"^ *", line)[0])  #  100000 loops, best of 3: 1.94 µs per loop
%timeit len(r.findall(line)[0])           # 1000000 loops, best of 3: 0.890 µs per loop
其他答案中的正则表达式速度较慢的原因是,正则表达式是在构造正则表达式时编译的状态机。内部有一个缓存,但即使如此,还是最好自己手工编译并重用正则表达式

但是,请注意,正则表达式解决方案的速度仅为第一个示例的20%(最坏的情况是,如果使用预编译表达式,则为43%),该示例比较了去除空白前后的字符串

重要注意事项:Python将制表符解释为8个空格的缩进,因此您还需要
。在求值之前,将()
文本制表符替换为相等的空格


编辑添加:Python解析器本身并不关心特定的缩进级别,只关心给定的“块”是否一致缩进。缩进的增加量实际上被忽略和剥离,取而代之的是缩进和DEDENT标记。(缩进16个空格)→ 只有一个缩进标记。)真正重要的是每行缩进的变化。

请注意,您选择的确定缩进的方法可能会对性能产生重大影响。例如,虽然您可以使用正则表达式来测量前导空格,但有更简单、更有效的方法

import re

line = '            Then the result is even.'
r = re.compile(r"^ *")

%timeit len(line) - len(line.lstrip())    # 1000000 loops, best of 3: 0.387 µs per loop
%timeit len(re.findall(r"^ *", line)[0])  #  100000 loops, best of 3: 1.94 µs per loop
%timeit len(r.findall(line)[0])           # 1000000 loops, best of 3: 0.890 µs per loop
其他答案中的正则表达式速度较慢的原因是,正则表达式是在构造正则表达式时编译的状态机。内部有一个缓存,但即使如此,还是最好自己手工编译并重用正则表达式

但是,请注意,正则表达式解决方案的速度仅为第一个示例的20%(最坏的情况是,如果使用预编译表达式,则为43%),该示例比较了去除空白前后的字符串

重要注意事项:Python将制表符解释为8个空格的缩进,因此您还需要
。在求值之前,将()
文本制表符替换为相等的空格

编辑添加:Python解析器本身并不关心特定的缩进级别,只关心给定的“块”是否一致缩进。压痕i的增加量