python缩进可以嵌套吗_反射 - 一行Python代码可以知道它的缩进嵌套级别吗?

反射 - 一行Python代码可以知道它的缩进嵌套级别吗?

从这样的事情:

print(get_indentation_level())

print(get_indentation_level())

print(get_indentation_level())

我想得到这样的东西:

1

2

3

代码可以用这种方式读取自己吗?

我想要的是更嵌套的代码嵌套部分的输出。 与使代码更易于阅读的方式相同,它将使输出更易于阅读。

当然,我可以使用例如手动实现这一点。 .format(),但我想到的是一个自定义打印功能print(i*' ' + string)其中i是缩进级别。 这将是在我的终端上进行可读输出的快速方法。

有没有更好的方法来避免辛苦的手动格式化?

5个解决方案

114 votes

如果你想在嵌套级别而不是空格和制表符方面进行缩进,那么事情会变得棘手。 例如,在以下代码中:

if True:

print(

get_nesting_level())

对get_nesting_level的调用实际上嵌套了一层深度,尽管tokenize调用行上没有前导空格。 同时,在以下代码中:

print(1,

2,

get_nesting_level())

对tokenize的调用是嵌套的零级深度,尽管其行上存在前导空格。

在以下代码中:

if True:

if True:

print(get_nesting_level())

if True:

print(get_nesting_level())

尽管领先的空白是相同的,但对tokenize的两次调用处于不同的嵌套级别。

在以下代码中:

if True: print(get_nesting_level())

是嵌套的零级别,还是一个? 对于正式语法中的tokenize和DEDENT令牌,它的深度为零,但您可能感觉不一样。

如果你想这样做,你将不得不将整个文件标记到通话点并计算tokenize和DEDENT令牌。 tokenize模块对于这样的功能非常有用:

import inspect

import tokenize

def get_nesting_level():

caller_frame = inspect.currentframe().f_back

filename, caller_lineno, _, _, _ = inspect.getframeinfo(caller_frame)

with open(filename) as f:

indentation_level = 0

for token_record in tokenize.generate_tokens(f.readline):

token_type, _, (token_lineno, _), _, _ = token_record

if token_lineno > caller_lineno:

break

elif token_type == tokenize.INDENT:

indentation_level += 1

elif token_type == tokenize.DEDENT:

indentation_level -= 1

return indentation_level

user2357112 answered 2019-04-28T03:44:52Z

21 votes

是的,这绝对是可能的,这是一个有效的例子:

import inspect

def get_indentation_level():

callerframerecord = inspect.stack()[1]

frame = callerframerecord[0]

info = inspect.getframeinfo(frame)

cc = info.code_context[0]

return len(cc) - len(cc.lstrip())

if 1:

print get_indentation_level()

if 1:

print get_indentation_level()

if 1:

print get_indentation_level()

BPL answered 2019-04-28T03:45:18Z

9 votes

您可以使用:获取行号。 然后,为了找到缩进级别的数量,您需要找到前一行零缩进,然后从该行的数字中减去当前行号,您将获得缩进的数量:

import sys

current_frame = sys._getframe(0)

def get_ind_num():

with open(__file__) as f:

lines = f.readlines()

current_line_no = current_frame.f_lineno

to_current = lines[:current_line_no]

previous_zoro_ind = len(to_current) - next(i for i, line in enumerate(to_current[::-1]) if not line[0].isspace())

return current_line_no - previous_zoro_ind

演示:

if True:

print get_ind_num()

if True:

print(get_ind_num())

if True:

print(get_ind_num())

if True: print(get_ind_num())

# Output

1

3

5

6

如果你想要使用:基于前面几行的缩进级别的数量,你可以稍微改变一下:

def get_ind_num():

with open(__file__) as f:

lines = f.readlines()

current_line_no = current_frame.f_lineno

to_current = lines[:current_line_no]

previous_zoro_ind = len(to_current) - next(i for i, line in enumerate(to_current[::-1]) if not line[0].isspace())

return sum(1 for line in lines[previous_zoro_ind-1:current_line_no] if line.strip().endswith(':'))

演示:

if True:

print get_ind_num()

if True:

print(get_ind_num())

if True:

print(get_ind_num())

if True: print(get_ind_num())

# Output

1

2

3

3

作为替代答案,这里是一个获取缩进数(空格)的函数:

import sys

from itertools import takewhile

current_frame = sys._getframe(0)

def get_ind_num():

with open(__file__) as f:

lines = f.readlines()

return sum(1 for _ in takewhile(str.isspace, lines[current_frame.f_lineno - 1]))

Kasrâmvd answered 2019-04-28T03:46:02Z

6 votes

>>> import inspect

>>> help(inspect.indentsize)

Help on function indentsize in module inspect:

indentsize(line)

Return the indent size, in spaces, at the start of a line of text.

Craig Burgler answered 2019-04-28T03:46:21Z

6 votes

要解决导致您的问题的“真实”问题,您可以实现一个上下文管理器,它跟踪缩进级别并使代码中的块结构对应于输出的缩进级别。 这样代码缩进仍然反映了输出缩进而没有太多耦合。 仍然可以将代码重构为不同的函数,并且基于代码结构具有其他缩进而不会弄乱输出缩进。

#!/usr/bin/env python

# coding: utf8

from __future__ import absolute_import, division, print_function

class IndentedPrinter(object):

def __init__(self, level=0, indent_with=' '):

self.level = level

self.indent_with = indent_with

def __enter__(self):

self.level += 1

return self

def __exit__(self, *_args):

self.level -= 1

def print(self, arg='', *args, **kwargs):

print(self.indent_with * self.level + str(arg), *args, **kwargs)

def main():

indented = IndentedPrinter()

indented.print(indented.level)

with indented:

indented.print(indented.level)

with indented:

indented.print('Hallo', indented.level)

with indented:

indented.print(indented.level)

indented.print('and back one level', indented.level)

if __name__ == '__main__':

main()

输出:

0

1

Hallo 2

3

and back one level 2

BlackJack answered 2019-04-28T03:46:49Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值